Auxiliary Systems
Custom Domains & Branded Links
Click a node to see what it does. Switch tiers above to see how the design scales.
Overview
A real, differentiating feature of a Bitly-style product: customers use
their own branded domain (go.acme.com) instead of the shared one. It’s a
good “expand on later” topic because it changes the shape of the redirect
lookup from single-tenant to multi-tenant, touching DNS and TLS along the
way — real depth, but squarely not part of the core three subsystems.
API Design
POST /api/domains
// request
{ "domain": "go.acme.com" }
// 201 Created
{
"domain": "go.acme.com",
"verification_status": "pending_dns",
"cname_target": "custom.shrt.design"
}
The customer points a CNAME record for go.acme.com at
custom.shrt.design. Once DNS and TLS are verified, links created under
that domain redirect from go.acme.com/{code} instead of the shared
domain.
Database Schema
CREATE TABLE custom_domains (
domain VARCHAR(255) PRIMARY KEY,
tenant_id BIGINT NOT NULL,
verification_status VARCHAR(20) NOT NULL DEFAULT 'pending_dns',
cert_status VARCHAR(20) NOT NULL DEFAULT 'pending',
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
ALTER TABLE urls ADD COLUMN domain VARCHAR(255) REFERENCES custom_domains(domain);
Basic Approach — Per-Domain Row, Single Shared Redirect Path
How it works
Store each verified custom domain in a table. On a redirect request, look
up which domain it arrived on (from the HTTP Host header) first, then
look up the code within that domain’s namespace.
Request (Host: go.acme.com, path /promo) ──▶ look up domain "go.acme.com"
└▶ look up code "promo" scoped to that domain ──▶ 302
Tradeoffs
- Pro: Minimal change to core Redirection — it’s the same lookup,
just keyed by
(domain, code)instead ofcodealone. - Con: Every custom domain needs its own valid TLS certificate for HTTPS, and provisioning and renewing one per customer domain on the fly is nontrivial infrastructure the single-domain version never needed.
Scaled Approach — Wildcard TLS Termination + Verification Pipeline
How it works
Rather than provisioning a certificate synchronously and blocking on it, an automated pipeline (e.g., ACME/Let’s Encrypt) verifies DNS ownership — the CNAME must resolve correctly — then requests and installs a certificate asynchronously, moving the domain from pending to active. The edge load balancer terminates TLS using SNI to pick the right certificate per incoming domain.
Customer adds CNAME ──▶ Verification Worker polls DNS ──resolves──▶ request cert via ACME
└▶ install at edge (SNI) ──▶ domain: active
Tradeoffs
- Pro: Customers don’t need a human in the loop or a deploy to go live — the whole onboarding flow is self-service and automatic.
- Pro: SNI-based termination means one edge fleet serves TLS for thousands of distinct customer domains without a dedicated IP each.
- Con: DNS propagation and certificate issuance both have real-world delays outside the system’s control — the product has to communicate a “pending” state honestly rather than pretending it’s instant.
- Con: A misconfigured or expired customer DNS record can silently break redirects for that one domain without affecting anyone else — worth having per-domain health checks rather than assuming “worked once” means “still works.”
Advanced Approach — Fully Multi-Tenant Routing with Isolation
How it works
As custom domains grow into the thousands, the domain-to-tenant lookup
itself needs to be as fast and cache-friendly as the code lookup already
is — a two-level cache: domain → tenant, then (tenant, code) → long_url. Rate limiting and click analytics become tenant-scoped rather
than global, so one customer’s traffic spike or abuse can’t affect
another’s limits or dashboards.
Request (Host header) ──▶ Edge Cache: domain → tenant_id (cached)
└▶ Edge Cache: (tenant_id, code) → long_url (cached) ──▶ 302
└▶ per-tenant rate limits & click analytics, scoped independently
Tradeoffs
- Pro: The redirect path stays just as fast for custom domains as for the shared domain, since the extra domain→tenant hop is cached at the edge, not a database round-trip per request.
- Pro: Per-tenant isolation means a noisy or abusive customer can’t exhaust rate limits or pollute analytics for a different customer, even on shared infrastructure.
- Con: Cache invalidation now has two layers instead of one — the domain mapping and the code mapping can each go stale independently.
- Con: True per-tenant isolation (separate rate-limit buckets, separate analytics rollups) is more data modeling and operational complexity than most companies need until they have many large customers.
Tech Choices
- DNS CNAME — the standard mechanism for a customer to point their domain at the shortener’s infrastructure without transferring ownership.
- SNI-based TLS termination — one edge fleet, one IP range, correct certificate served per incoming domain.
- ACME / Let’s Encrypt-style automation — self-service certificate issuance with no manual step.
- Multi-tenant caching (
domain → tenant → code) — keeps custom-domain redirects as fast as the shared-domain path.
How to Vocalize This in an Interview
Bring this up only if the interviewer explicitly asks about branded or custom links — it’s real depth (TLS, DNS, multi-tenancy all at once), but it’s squarely a “later” subsystem, not part of the core three worth naming in minute one.