1---
2title: Custom domains
3description: Register a Function hostname, configure DNS and CAA, verify HTTPS, and retire the domain safely.
4---
5
6A Neon custom domain maps one hostname to one Function on one branch. Alchemy
7registers that mapping and returns the DNS target; your DNS provider and Neon
8certificate provisioning complete the setup. Start with [Setup](/neon/setup) and
9a Function whose native URL already works.
10
11## Prepare a hostname
12
13Use a domain you control and arrange permission to edit its DNS. Prefer a
14subdomain such as `api.example.com`: a standard CNAME cannot be placed at a zone
15apex without provider-specific flattening. Reserve a different hostname for each
16preview; custom domains are not inherited by child branches.
17
18Confirm whether another application already uses the hostname before changing
19its records. A hostname can belong to only one Function target at a time.
20
21## Register the Function domain
22
23Inside your stack, using an existing `api` Function:
24
25```typescript
26import * as Neon from "alchemy/Neon";
27
28const domain = yield* Neon.CustomDomain("ApiDomain", {
29 function: api,
30 hostname: "api.example.com",
31});
32```
33
34Return `domain.cnameTarget` in the stack outputs so the DNS operator can copy the
35exact target after deployment. Registration intentionally does not wait for DNS,
36which lets you create the DNS record afterward.
37
38## Use the Website alternative
39
40For a Website, use its `domain` prop instead of declaring a second registration
41for the same hostname:
42
43```typescript
44const site = yield* Neon.Website.Vite("Web", {
45 branch,
46 rootDir: "./web",
47 domain: "app.example.com",
48});
49```
50
51The live Website exposes the registration as `site.domain` and its target as
52`site.domain.cnameTarget`. During native local development there is no domain
53registration; use the local dev URL. A returned custom URL is not proof that DNS
54or HTTPS is ready.
55
56## Publish a DNS-only CNAME
57
58At your DNS provider, configure:
59
60| Field | Value |
61| --- | --- |
62| Type | `CNAME` |
63| Name | `api` or `api.example.com`, according to the provider's UI |
64| Target | The exact `cnameTarget` output, without `https://` or a path |
65| Proxy | Disabled / DNS-only; on Cloudflare this is the grey cloud |
66| TTL | Your DNS provider's normal value |
67
68After reviewing their ownership, remove conflicting A, AAAA, or CNAME records for
69that hostname. A proxy can prevent Neon validation even when the browser appears
70to reach an edge server. Wait for the applicable DNS TTL before judging propagation.
71
72## Check certificate-authority restrictions
73
74If your domain or an applicable parent has CAA records, the policy must allow
75Let's Encrypt, the certificate authority Neon uses. Have the DNS/security owner
76approve the change, then authorize it as described in
77[Neon's domain guide](https://neon.com/docs/compute/functions/custom-domains#configure-dns):
78
79```text
80CAA 0 issue "letsencrypt.org"
81```
82
83A domain without a restrictive CAA policy does not need this extra record merely
84to satisfy Alchemy.
85
86## Check registration status
87
88In the Neon Console, select the project and branch, then open **Settings →
89Functions → Custom Domains**. Check the target Function, DNS status, and any
90reported reason. The resource also exposes `status`, `dnsStatus`, `bindingStatus`,
91and `statusReason` when returned by Neon.
92
93| Reported problem | Action |
94| --- | --- |
95| `cname-not-pointing-at-edge` | Correct the target, disable DNS proxying, remove conflicts, and allow propagation |
96| `caa-blocks-lets-encrypt` | Review CAA on the hostname and its parent domains; authorize Let's Encrypt |
97| `binding-missing` | Verify the intended Function still exists; contact Neon Support if internal routing remains missing |
98| Hostname already registered elsewhere | Resolve ownership of the existing mapping; do not bypass it with blanket adoption |
99
100## Verify HTTPS and application behavior
101
102Resolve the public CNAME:
103
104```sh
105dig +short CNAME api.example.com
106```
107
108Then request a known route that your Function implements:
109
110```sh
111curl --fail-with-body --max-time 30 https://api.example.com/health
112```
113
114Check the expected response, not only a successful status. Keep TLS verification
115enabled; `curl -k` would hide a certificate failure. Neon may issue the certificate
116on the first request. If the registration is active but HTTPS initially fails,
117allow a short issuance delay and retry once; persistent failures need diagnostics,
118not an unbounded retry loop.
119
120Open the application through the custom hostname and exercise sign-in, navigation,
121redirects, and any streaming/WebSocket features it uses. Registration status
122`active` establishes DNS/CAA/routing, not completed application acceptance.
123
124## Secure both URLs
125
126The native Neon Function URL remains public when a custom domain is added.
127Authenticate and authorize protected work on both entry points. Browser clients
128may also require application CORS configuration. For Auth redirects, register the
129custom application's origin separately using
130[Production Auth](/neon/guides/production-auth).
131
132## Retire the hostname
133
134Remove the DNS record first, then wait for public DNS to stop returning the Neon
135target. Only then remove the CustomDomain declaration and deploy, or destroy its
136owning stack. This avoids leaving a dangling CNAME after releasing the hostname.
137If DNS is managed in a separate stack or by another team, coordinate the ordering
138rather than assuming Function destruction also removes DNS.
139
140Confirm the custom URL no longer serves the retired application before reusing
141the hostname. Keep the original stack/stage state until cleanup finishes; see
142[State and recovery](/neon/guides/state-recovery).
143
144## Related guides
145
146- [CustomDomain reference](/providers/neon/customdomain) — inputs, outputs, and lifecycle.
147- [Neon custom domains](https://neon.com/docs/compute/functions/custom-domains) — current DNS, CAA, and status behavior.
148- [Setup](/neon/setup) — deployment prerequisites.