How to Know a System Is Actually Ready
Running and correct aren't the same as ready. A practical checklist for the gap between a demo that works and a system you can trust with real use.
CONTEXT
A framework for deciding when a tool, automation, or pipeline has crossed the line from "built" to "ready for real use" — written for solo developers and small teams who don't have a platform org to lean on.
"It works" is the lowest bar a system clears. It compiled, the happy path ran, the demo didn't crash. None of that tells you what happens the second time someone uses it, the first time the network blips mid-write, or the day you're not the one operating it. Readiness is a different question from correctness, and conflating the two is how internal tools quietly become load-bearing infrastructure nobody trusts.
Compiles is not correct, and correct is not ready
There are three separate bars, and most projects only clear the first two before someone calls them done:
- It runs. No crashes on the input you tried.
- It's correct. It produces the right output for the inputs you thought to test.
- It's ready. It produces the right output — or fails safely and visibly — for the inputs you didn't think to test, under conditions you don't control, when you're asleep.
The third bar is the expensive one, which is exactly why it gets skipped. It doesn't show up in a demo. Nobody claps when a retry doesn't double-charge a customer. But it's the only bar that matters once a system is doing something for someone other than its author, on a schedule its author doesn't control.
The signals that actually predict trouble
None of these are process for its own sake — each one maps to a specific failure mode that shows up in production and nowhere else.
Test coverage of the failure modes, not the feature. A test suite that only exercises correct inputs tells you the system works when everything goes right, which is the one condition you don't need reassurance about. What matters: What happens on a duplicate webhook? A response that times out at 29 of 30 seconds? A record that was deleted between the read and the write? If you can't name three ways this fails and point to a test for each, you don't know if it's ready — you know it's plausible.
Idempotency and retry safety. If a job, a webhook handler, or a scheduled task can run twice — and eventually, something will make it run twice — does the second run do nothing, or does it duplicate a charge, double-send an email, or corrupt a count? This is the single most common gap between a working prototype and a production system, because it's invisible until a retry actually happens, and retries are the normal case at scale, not the exception.
Monitoring and alerting that tells you before a user does. Logs are not monitoring. If the only way you find out a nightly job failed is a user asking why their data is stale, you don't have observability, you have archaeology. The bar is low: one alert on the failure path, one heartbeat that says the job ran at all. That's a few hours of work, and it's the difference between finding out in five minutes and finding out in five days.
A rollback plan that exists before you need it. Not a disaster-recovery binder — just an honest answer to "if this deploy breaks something at 2pm on a Tuesday, what do I do?" If the answer is "figure it out," that's the answer you'll be improvising under pressure, with a stakeholder watching. Write it down before you need it, even if it's three lines.
Someone other than the builder has used it — without you in the room. This is the cheapest test on the list and the most skipped. You know the escape hatches, the input formats that break it, the field you have to leave blank. A second person doesn't. Every workaround you've internalized without noticing is a bug you've stopped seeing. Handing it off and watching, silently, is worth more than another week of solo QA.
Error messages that tell the user what to do, not just that something went wrong. "An error occurred" is a dead end. "The uploaded file exceeds 10MB — split it or use the bulk import" is a resolved ticket that never got filed. If your error paths are copy-pasted catch (e) { console.log(e) }, the system isn't ready — it's just quiet about being broken.
Data integrity that's verified, not assumed. If a pipeline imports, transforms, or syncs data, you need a way to check that what came out matches what should have come out — a row count reconciliation, a checksum, a spot-check query — that isn't "it looked fine when I glanced at it." Assumed integrity is the failure mode that doesn't announce itself; it just quietly produces wrong numbers that someone makes a decision on.
MVP-ready vs operationally-ready
These get treated as the same milestone and they aren't. MVP-ready means the core value proposition is provably real — the thing does the thing, for the case you built it for. Operationally-ready means the thing survives contact with conditions you didn't design for: bad input, partial failure, concurrent use, the builder being on vacation.
A system can be a legitimate, valuable MVP and still not be safe to point real users or real money at yet. That's not a failure — shipping an MVP to get signal is correct. The failure is treating MVP-ready as if it were the finish line, handing it to a client or letting it run unattended, and finding out the difference the hard way. The two milestones deserve two different conversations with whoever's waiting on the thing: "this proves the idea works" is not the same sentence as "you can rely on this."
A checklist that fits in your head
Enterprise readiness reviews exist because large orgs need an auditable gate with many stakeholders. A solo developer or small team doesn't need that theater — they need a list short enough to actually run before every real handoff:
- Can I name the top 3 ways this fails, and does a test cover each one?
- If a job or request runs twice, is the second run harmless?
- Will I find out about a failure before a user tells me?
- If today's deploy is bad, do I know the exact steps to undo it, right now, without thinking?
- Has someone who isn't me used this without me coaching them through it?
- When it fails, does the error say what to do next — not just that it broke?
- If it touches data, do I have a way to verify the output is correct, or am I trusting that it probably is?
Seven questions. If you can answer all seven honestly, the system is ready for real use — not perfect, not enterprise-hardened, but trustworthy enough to stop babysitting. If you can't, you don't have a readiness problem, you have a clarity problem: you don't yet know which of these seven is your actual risk, and that's worth finding out before someone else does.