Koo Docs
View as Markdown

Custom domains

Every web service you expose gets a default HTTPS URL from its first deployment. You can also point your own domains at it — delivered over HTTPS with a certificate Koo issues and renews for you.

Domains belong to the service: any exposed web service can hold its own set of custom domains, each with its own DNS records and live status.

The default URL

When you expose a web service, Koo's hosting layer assigns it a public URL on koo.app automatically. There is nothing to configure: HTTPS is included, with the certificate managed for you.

The URL is the first entry of the service's address list in the console (under Settings → Networking), and the status.url field on the Service object. The field is sticky — set once the service first goes live, and kept from then on; whether the service is currently up is its health, not its URL.

A custom domain adds a hostname. The default URL keeps working alongside it — nothing replaces it.

Add a custom domain

The service must be deployed and exposed first. Exposing is a staged change — turn on Public networking in the service's Settings → Networking and press Deploy; see staged changes. Domains themselves are different: adding or removing one applies immediately, with no deploy step.

In the console:

  1. Open the service's drawer and go to Settings → Networking.
  2. Below the Public networking toggle, the service's address list shows its default URL and every custom domain. Click Custom domain.
  3. Enter the hostname — for example app.example.com — and click Add domain.

Over the API. Write the full desired set of hostnames through a service update, as a domains array of strings. Domains are declarative on the service and the hostname is its own identity — there are no domain IDs to track.

json
{  "domains": ["app.example.com", "www.example.com"]}

The array is the complete desired state: a hostname you leave out is removed. Read each hostname back on the service's read-only domains array, where every entry is enriched with the DNS records to set and its live status.

Set the DNS records

As soon as you add a hostname, Koo returns the exact DNS records to create — an ownership record and a routing record. The console shows each record's name and value with copy buttons, and keeps them visible even after the domain goes live; over the API they come back on the service's domains[].dnsRecords. Don't guess the values — set exactly what Koo returns, at your DNS provider.

PurposeTypeWhat to set
OwnershipTXTThe name and value Koo shows for the hostname
RoutingCNAMEThe target Koo shows for the hostname

Routing is always a CNAME, for both subdomains and apex domains. Because the DNS standard doesn't allow a CNAME at the zone root, point an apex domain (like example.com) at Koo's target using your DNS provider's CNAME flattening — often labelled ALIAS or ANAME. You never configure NS delegation, and Koo never asks you to.

Verification, routing, and TLS

Once the records are set, Koo takes it from there — you don't trigger anything. A domain walks a simple lifecycle, readable from its status on the service:

  • pending — added, but the records aren't proven yet.
  • verifying — the records are accepted, and DNS and the certificate are being set up.
  • active — traffic routes to your service and HTTPS is live. Koo issues the certificate automatically on port 443 and renews it for you; you never upload or renew a certificate.
  • error — something is off. When the cause is known — a record that doesn't resolve, say — it shows under the status, and as statusReason on the API.

While a domain is pending or error, Koo re-checks it automatically about once a minute, so you just set the records and wait — there is no verify button to press. A domain is never marked active until DNS and the certificate are both real, so the status you see is the truth.

Remove a domain

Remove a hostname in the console — the trash button on its row, with an inline confirm — or leave it out of the service's domains array on the next update. Removal applies immediately: traffic on that hostname stops routing right away, while the default URL and any other custom domains keep working. To restore it, add it again and re-set the DNS records.

Plan limits

Custom domains aren't included on the Free plan. Every paid plan includes them, with a cap that rises by tier — see usage and limits for the numbers.

When you reach your plan's cap, the console blocks adding another domain and names the plan that raises it, and the API returns a quota error naming the tier to upgrade to. Plan changes happen in Billing.