PandaStack

Custom Domains

Serve your app on your own domain — add it, create two DNS records, and TLS is issued and renewed automatically. Subdomains and apex domains supported.

Every app gets a stable https://<app-id>.pandastack.ai URL. Custom domains let you serve the same app on your own domainapp.acme.com, or the apex acme.com — with TLS issued and renewed automatically. No certificates to manage, nothing to renew, nothing extra to pay.

How it works

  1. Add the domain to your app (dashboard, API, or SDK).
  2. Create two DNS records at your DNS provider — the exact records are shown when you add the domain:
    • a TXT record that proves you control the domain, and
    • a CNAME pointing the domain at ingress.pandastack.ai (apex domains use ALIAS/ANAME instead — see below).
  3. Wait for DNS to propagate — verification and certificate issuance then complete automatically, typically within a few minutes. The domain shows pending → verified → active; at active it serves traffic.

Your custom domain behaves exactly like the default URL: blue-green deploys, scale-to-zero and wake-on-request, previews of build logs — everything is identical. The domain survives every deploy.

Adding a domain

Open your app → Custom domains → enter the domain → Add domain. The panel shows the DNS records to create and live status; it refreshes automatically until the domain is active.

curl -X POST https://api.pandastack.ai/v1/apps/$APP_ID/domains \
  -H "Authorization: Bearer $PANDASTACK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain": "app.acme.com"}'

The response's records array lists the DNS records to create. Poll GET /v1/apps/{id}/domains/{domain} until status is "active".

import { PandaStack } from "@pandastack/sdk";

const ps = new PandaStack();
const d = await ps.apps.addDomain(appId, "app.acme.com");
for (const r of d.records) {
  console.log(`${r.type}  ${r.name}  →  ${r.value}`);
}
// later:
const status = (await ps.apps.getDomain(appId, "app.acme.com")).status;
from pandastack import PandaStack

ps = PandaStack()
d = ps.apps.add_domain(app_id, "app.acme.com")
for r in d["records"]:
    print(f"{r['type']}  {r['name']}{r['value']}")
# later:
status = ps.apps.get_domain(app_id, "app.acme.com")["status"]

Apex domains

A bare apex (acme.com) cannot hold a CNAME record — that's a DNS rule, not ours. Use whichever your DNS provider offers:

  • ALIAS / ANAME recordingress.pandastack.ai (Route 53, DNSimple, NS1, …)
  • CNAME flattening (Cloudflare does this automatically for apex CNAMEs)

The TXT verification record works the same either way.

Statuses

StatusMeaningWhat to do
pendingWaiting for your TXT recordCreate the records; DNS can take minutes to propagate
verifiedOwnership proven, certificate issuingNothing — usually completes in minutes
activeServing traffic with TLSDone
errorSomething actionable is wrongRead the message — it names the exact problem (record missing, points elsewhere, …)

The dns_note field always describes what the platform currently observes ("TXT not found yet", "DNS points at X, expected Y"), so you never have to guess which record is wrong.

Already proxying through Cloudflare? If your domain is on Cloudflare with the orange cloud on, issuance still works — but during initial setup prefer DNS-only (grey cloud) for the record if activation seems stuck, and re-enable proxying after the domain turns active.

Removing a domain

Deleting a domain stops traffic on it immediately and deprovisions its certificate. Deleting the app removes all of its domains automatically.

Limits & notes

  • A domain can be attached to one app at a time, across all workspaces — first verified owner holds it.
  • Wildcard domains (*.acme.com) are not supported; add each hostname.
  • The verification TXT record is safe to delete after the domain turns active — a working production domain is never torn down because a verification record was cleaned up later.

On this page