Routing Service
Atomic domain and gateway configuration management
Routing Service
The RoutingService
manages atomic domain assignment and gateway configuration updates, ensuring consistency between control plane (domains DB) and data plane (gateway configs).
Location: go/apps/ctrl/workflows/routing/
Proto: go/proto/hydra/v1/routing.proto
Key: project_id
Why Separate Service?
Domain and gateway operations are the critical section of deployments:
- Must be atomic - both succeed or both fail
- Must be serialized per project to prevent race conditions
- Should not block non-routing operations (like building containers)
By separating routing, we:
- Allow multiple deployments to build in parallel
- Serialize only the sensitive routing mutations
- Provide clear boundaries for concurrency control
Operations
AssignDomains
Creates or reassigns domains to a deployment:
- For each domain: find existing or insert new domain record
- Skip domains marked as rolled back
- Prepare gateway configs (exclude local domains like
.local
,.test
) - Bulk upsert gateway configs to partition database
- Return list of changed domains
Implementation: go/apps/ctrl/workflows/routing/assign_domains_handler.go
Domain Sticky Levels:
UNSPECIFIED
: Per-commit domains (e.g.,abc123.domain.com
)BRANCH
: Branch-level (e.g.,main.domain.com
)ENVIRONMENT
: Environment-level (e.g.,staging.domain.com
)LIVE
: Production domain (e.g.,domain.com
)
SwitchDomains
Reassigns existing domains to a different deployment:
- Fetch target deployment's gateway config
- Fetch domain records
- Upsert gateway configs first (data plane ready)
- Reassign domains (control plane pointers updated)
Implementation: go/apps/ctrl/workflows/routing/switch_domains_handler.go
Order of Operations
Critical: Gateway configs are always updated before domain reassignment. This ensures:
- Gateway is ready to serve traffic before DNS/routing points to it
- No downtime during switches
- Rollback is possible if domain update fails
Local Domain Filtering
Domains with .local
or .test
TLDs, or localhost
/127.0.0.1
are excluded from gateway config generation since they're for local development only.
Helper: go/apps/ctrl/workflows/routing/helpers.go:isLocalHostname()