The reference platform
This is the target state we build toward. Not every client needs all of it on day one — a Series A with one region and eleven services should not be running active/active — but this is the shape the modules assume, and it is what the migration path converges on.
Multi-region active/active
Two regions serving live traffic, routed by health and latency. Losing a region is a capacity event, not an outage. Everything below the edge is reproducible from Git and Terraform in under four hours.
The SLO matrix
Every service gets a tier. The tier is not a label — it drives replica floors, node class, disruption budgets, on-call routing and how much of the roadmap gets frozen when the error budget is spent.
| Tier | Availability | Budget / 30d | Latency p99 | Alerting | Placement | RTO / RPO |
|---|---|---|---|---|---|---|
| tier-0 | 99.95% | 21m 36s | 120 ms | Page 24/714.4× 1h · 6× 6h | Multi-region, on-demand floormin 6 replicas, PDB 50% | 90s / 30s |
| tier-1 | 99.9% | 43m 12s | 250 ms | Page business hours6× 6h · ticket otherwise | Single region, 3 AZmin 3 replicas, PDB 50% | 15m / 5m |
| tier-2 | 99.5% | 3h 36m | 800 ms | Ticket only | Spot eligible, 2 AZmin 2 replicas | 4h / 1h |
| batch | Completion SLO99% within window | n/a | Job duration p95< 40 min | Ticket on 2 consecutive misses | 100% spot, checkpointed | next run / 0 |
Security & compliance
We are not an audit firm and we will not sell you a certification. What we do is build the platform so that the controls your auditor asks about are enforced by a machine and evidenced automatically.
Identity & access
No long-lived cloud credentials anywhere in the delivery path. Workloads use IRSA/Workload Identity; pipelines use OIDC federation; humans get short-lived, session-recorded, break-glass access that pages when used.
- OIDC federation
- IRSA
- SSO + SCIM
- Break-glass audit
Supply chain
Images are built from distroless bases in an ephemeral runner, produce an SPDX SBOM, get scanned, and are signed with cosign. The admission controller rejects anything without a valid signature from our key — including in staging.
- SLSA L3 target
- Cosign
- SPDX SBOM
- Trivy gate
Network
Default-deny in both directions. Cilium network policies are generated from the declared dependency graph, so a service can only reach what it said it needs, and egress to the internet goes through an allowlisted proxy with DNS logging.
- Default deny
- mTLS east-west
- Egress proxy
- Private endpoints
Data
Encrypted at rest with customer-managed keys and in transit end to end. Secrets never live in Git — External Secrets pulls from Vault or the cloud secret manager at runtime, with rotation windows defined per secret class.
- CMK / KMS
- Vault
- External Secrets
- PITR backups
Evidence
Control evidence is generated, not gathered. Policy decisions, admission rejections, access grants and change approvals stream to an immutable log that maps onto SOC 2 and ISO 27001 control IDs.
- SOC 2 Type II
- ISO 27001
- GDPR / data residency
Resilience testing
Backups that have never been restored are not backups. We drill database restore monthly, region promotion quarterly, and run failure injection game days against production dependencies during working hours.
- Restore drills
- Region failover
- Chaos injection
package gridworks.admission
# Reject any pod whose images are not signed by the platform key.
# Applies to every namespace except kube-system. No exceptions list.
deny[msg] {
input.request.kind.kind == "Pod"
not input.request.namespace == "kube-system"
container := input.request.object.spec.containers[_]
not signed(container.image)
msg := sprintf(
"image %v is unsigned or signature is not verifiable",
[container.image])
}
# Digest-pinned images only — tags are mutable, digests are not.
deny[msg] {
container := input.request.object.spec.containers[_]
not contains(container.image, "@sha256:")
msg := sprintf("image %v must be digest-pinned", [container.image])
}
Getting there without a big bang
Nobody moves a production estate in one weekend. We move it in waves, ordered by blast radius, with the old path kept warm until the new one has held real traffic for two weeks.
- Least critical service first — internal tooling, then read paths, then writes, then money
- Traffic shifts at 5 / 25 / 50 / 100% with a soak period between each step
- Old path stays deployable for 14 days after 100%; rollback is a DNS weight change
- Every wave has a named rollback owner and a tested rollback command, run in staging first
- Data moves last and only behind dual-write plus reconciliation, never a dump-and-restore cutover
- A wave is not "done" until the SLO has held for two full weeks on the new path
- Typical estate
- 60–140 services, 12–20 weeks
- Planned downtime
- zero, including the database wave
- Rollback SLA
- < 5 minutes to previous path
What lands in your repos
On the last day of an engagement you own everything. There is no GridWorks-licensed component, no agent phoning home, and nothing that stops working if you never speak to us again.
$ tree -L 2 platform/ platform/ ├── terraform/ # 41 modules, versioned + tested (terratest) │ ├── network/ vpc · subnets · tgw · dns · egress proxy │ ├── clusters/ eks · node pools · irsa · addons │ └── data/ rds · elasticache · msk · s3 lifecycle ├── crossplane/ # self-service claims for app teams ├── argocd/ # app-of-apps, per-env overlays, RBAC ├── policy/ # rego + kyverno, unit tested in CI ├── observability/ # collectors · dashboards · slo rules ├── runbooks/ # 38 runbooks, linked from every alert │ ├── region-failover.md │ ├── postgres-restore.md │ └── cluster-upgrade.md └── docs/ # adrs · onboarding · golden path tutorial ✓ licence your code, no restrictions ✓ dependencies upstream open source only ✓ access our accounts removed on day of handover
Bring us your architecture diagram
Ninety minutes, one principal engineer, no slides. We will tell you which parts of this you actually need and which parts would be over-engineering for your stage.