Owner: the founder. Approved: 2026-10-08. Review: annually, and after every restore drill.
| Dependency | Failure means | Substitute |
|---|---|---|
| Neon Postgres | total outage; all state is here | none — this is the hard dependency |
| Hetzner node (CCX23, Ashburn) | total outage | rebuild from git on a new node |
| Cloudflare DNS (records are DNS-only — not proxied; there is no CDN or WAF in the request path) | the domain stops resolving | the zone could be moved to another DNS provider |
| Cloudflare R2 | uploaded documents and generated PDFs unavailable | none |
| WorkOS | nobody can sign in | none |
| Postmark | no outbound or inbound e-mail | none |
| Stripe | no new subscriptions; existing service unaffected | none |
| Anthropic (the only LLM provider) | workers cannot produce output; the app still serves | the app degrades, it does not fail |
| The founder | everything stops | none — this is the largest single risk |
.env is in no backup by design, and its loss means
re-issuing every credential from the vendor consoles.NEON_API_KEY and the Neon project id in
the production .env, and until then every run records "not configured"
(docs/security/evidence/restore-drills.md). A backup nobody has restored is
a hypothesis about a backup — so the objectives in §4 are targets, not
measurements.infrastructure/deploy/docker-compose.yml, §"CONTAINER LOGS"); for
an incident, they are saved by hand before the fix is deployed.The drill and the snapshot evidence cost founder-hours and no money; the off-provider copies need a decision on retention first.
This is the one statement of RTO and RPO. The disaster-recovery runbook
(docs/runbooks/disaster-recovery.md §0) carries the same table with the
step-by-step for each scenario, and the restore-drill evidence file quotes it;
where they ever disagree, this table is corrected and the others follow it.
| Scenario | RPO (data we can lose) | RTO (until customers are served again) |
|---|---|---|
| A. Application broken, data fine | 0 | ≤ 1 hour — redeploy a known-good ref |
| B. Database damaged (bad migration, bad script, mass delete) | ≤ 5 minutes — Neon point-in-time restore | ≤ 2 hours |
| C. Objects in R2 lost or overwritten | whatever R2 no longer holds — there is no second copy | ≤ 1 hour to serve again; lost objects stay lost |
| D. Node lost (hardware, account, compromise) | 0 for data (it lives in Neon and R2) | ≤ 4 hours — new CCX23 from the snapshot, deploy, DNS switch |
Read with these conditions, because each one is where the number stops being true:
.env
with it. Without one, every credential is re-issued from its console and
customers reconnect their integrations — far longer, and not covered here.Monthly, automated — backup_restore_drill, first Sunday of the month at
03:00 UTC (or scripts/restore_drill.py by hand): a Neon branch from the latest
point in time, row counts on five core tables against production, the RLS
policies on the copy, the result in the audit log and the evidence file, the
branch deleted (docs/runbooks/restore-drill.md). It has not run yet — see
§3.
Annually, by hand, the parts a script cannot answer. Four hours:
alembic current against it and confirm the revision matches production.docs/runbooks/disaster-recovery.md §B step 6 is the
procedure.)Every external side-effect surface is flag-gated, so degradation is a switch,
not a rollback. The cost guardrails double as a blast-radius control: the
per-tenant cap and the global kill switch stop LLM and vendor spend without
taking the application down. Health probes — /health, /health/deep,
/healthz/jobs, /healthz/liveness, /healthz/deps — are what Better Stack watches and what the
deploy polls before declaring success.
Container resources are capped per service against the node's 4 vCPU and 16 GB, with the ingress deliberately uncapped so it always has room; the deploy trims the build cache to a budget after the health check, because the disk once reached 85 % of 150 GB unnoticed.
One person operates everything and holds every credential. This is disclosed, not
mitigated. The minimum mitigation, when there is anyone to hand it to: a sealed
credential escrow, a named backup incident commander, and the joiner checklist in
access-control.md §8. Until then, the honest statement to a customer is that
Ataski's continuity depends on one person — which is exactly what the terms and
the incident-response plan already say.