This is the actual checklist we run before signing off on a launch. It is ordered by consequence, not by effort: everything in the first section can lose you data or customers today, and everything in the last section only costs you sleep.
Copy it, run it against your own project, and be honest about the boxes you cannot tick. An unticked box is not a failure — it is a decision you have not made yet.
1. Security
- RLS enabled on every public table
- No
using (true)policy on any table holding user-specific data - Explicit policies per operation; every
insertandupdatehas awith_check - Privilege flags live in a table users cannot write
- No service-role or secret key reachable from the browser bundle
- Storage buckets have policies, and public buckets hold nothing private
- Serverless functions verify the caller's JWT rather than trusting a
user_idin the body - Auth redirect URLs allowlisted to your real domains
- Signups disabled or gated if the app is invite-only
- Dependencies audited with no known criticals
- Security headers set: HSTS,
X-Content-Type-Options, a real CSP
The first five are the ones that lose data rather than time. The five RLS mistakes covers the SQL for them, and the key audit covers the fifth.
2. Data integrity
- Every input validated at the boundary with a runtime schema
- Database constraints match application assumptions —
not null,check,unique, foreign keys with an expliciton delete - Multi-step writes wrapped in transactions
- Migrations versioned, reviewed, and reversible
- Automated backups on, and a restore actually performed once
- Money stored in integer minor units, never floats
A backup you have never restored is a hypothesis. Restoring one into a scratch project takes an hour and converts it into a fact.
3. Observability
- Error tracking wired up, alerting somewhere you will actually see it
- Uptime monitoring on the critical user paths, not just
/ - Structured logs with a request ID you can trace end to end
- No swallowed exceptions — no bare
catchthat only logs - Release version attached to every error, so you can tell which deploy did it
- A dashboard answering "is it up and is it fast" in one glance
4. Performance
- No N+1 query patterns on any list view
- Indexes on every column used in a
where, anorder by, or a join — including the columns your RLS policies filter on - Every list query paginated and bounded with
limit - Images sized, compressed, and lazily loaded below the fold
- Core Web Vitals measured on a real mid-range phone, not your laptop
- Caching headers set on static assets
5. Resilience
- Timeouts on every outbound call
- Retries with backoff where retries are safe, idempotency keys where they are not
- Rate limiting on public endpoints, auth routes, and anything that spends money per call
- Upload size and type limits enforced server-side
- Graceful degradation when a third party is down
- Spend caps set on every metered API
- A rollback path, tested at least once
6. Release hygiene
- An environment that mirrors production, separate from it
- CI running typecheck, lint, and tests on every push
- A health check endpoint the platform actually watches
- A runbook for the three most likely failures
- Someone owns the pager for launch week
Scoring yourself
Count what you cannot tick.
| Unticked | What it means |
|---|---|
| 0–3 | You are in good shape. Launch. |
| 4–10 | A focused week closes this. Prioritise sections 1 and 3. |
| 11–20 | Do not launch yet. Fix security and data integrity first. |
| 20+ | The prototype is fine; the production version has not been built yet. |
Most AI-generated codebases we see land between 15 and 25 on the first pass. That is normal, and it is not a judgement on the tools or on you — it is the predictable distance between "it works" and "it holds".
How to actually use it
Do not try to clear the whole list. Work it in three passes.
- Read all six sections without fixing anything. You are building the list, not working it. Fixing as you go means section 1 gets your best attention and section 5 gets none.
- Fix everything in section 1, then stop and re-run it. Security work has a habit of moving other boxes — closing a policy often breaks a query that a permissive policy was quietly holding up.
- Sequence the rest by what a failure would cost, not by what is quickest. The tempting order and the correct order are rarely the same.
Two to five days of focused work is the usual span for a prototype in that 15-to-25 range, and what that costs is written up with real ranges rather than "it depends".
If you would rather have this run against your codebase — findings written up, prioritised, and fixed — that is exactly what a production sprint is, and how it works is set out step by step. It starts with a free 15-minute launch audit: no pitch, no obligation, and you keep the findings either way.



