Stability levels in practice
A Stability level tells everyone how stable something is right now. It exists so you can move fast: show work early, get feedback, and move it up as soon as it's ready, without anyone mistaking rough work for something finished. This page covers how to use stability levels with clients, and what's typically expected at each level.
Stability levels explains what each level means from the client's side. Marking stability levels covers labels, versioning, and the badge components.
Use stability levels to move fast
- Show work early. A prototype on the second day of a block is worth more than a polished feature on the last, because the client can still change direction. The level is what makes showing rough work safe.
- Invest only what the current level needs. Don't build GA error handling into something the client hasn't seen yet. Get the direction right first, then harden what survives.
- Move up as soon as it's ready. You don't need a checkpoint, a review, or anyone's sign-off to move from Prototype to Alpha. Use your judgment and tell the client.
- Expect any pace. A feature can go from Prototype to GA within one iteration, or stay in Beta for several while real use shakes out the edge cases. Moving between levels walks through a feature that went through every level in one block.
Setting expectations with the client
Clients don't read test coverage or dashboards. They decide what to depend on, and the stability level is how we tell them, in one word, what the work can bear.
-
Say the level whenever you show something, and what it means for them:
Level What to tell the client Prototype "React to this and tell us which direction is right. Expect it to change completely." Alpha "Try it with real work and tell us what's wrong. Expect it to change, and keep your fallback." Beta "Use it for real. We'll tell you before anything changes, and keep a fallback for anything critical." GA "It's ready for anything. It will keep working the way it does now." -
Check with the client before moves that change what they rely on. Putting a feature in front of their real users, or calling it GA, needs their yes. A quick message is enough: "Invoice export is at Beta. Can we try it with a few of your finance team this week?" Other moves, just tell them.
-
Label it for what it is, not what you hope. If something isn't as stable as its level says, tell the client and fix the label or the work. A level that overstates stability is how a client ends up depending on something that isn't ready.
-
Name the gaps. Say what's still missing for the next level, such as "no alerts yet" or "untested above ten thousand rows," so the client can judge the risk themselves.
-
Say what's worth hardening next. Not everything needs to reach GA. Point out the features the client is starting to depend on, since those are the ones worth getting there.
When the client needs GA soon
If a deadline is close and the client wants something GA, explain what GA promises: it keeps working, it's monitored, and breaking changes wait for a new version. Then offer the options:
- Harden it now, using the checklist below to show what's left.
- Narrow what goes GA to the part they actually depend on, and leave the rest at Beta.
- Agree an exception for a specific item, such as "GA without mobile support," and note it in the release notes so no one is surprised later.
Checklists for each level
These checklists are what we typically expect at each level. They're a guide to help you judge when something is ready, not a gate or a sign-off form.
At a glance
| Prototype | Alpha | Beta | GA | |
|---|---|---|---|---|
| Code structure | Throwaway is fine. | Structured to change. | Structured to last. | Maintainable by the next engineer. |
| Tests | The demo path, checked by hand. | The main path. | Edge cases and error paths, in CI. | Thorough, reliable, and guarding against regressions. |
| Edge cases and errors | Can be ignored, but write them down. | Fail visibly, never silently. | Handled, with a helpful message. | Handled or documented as out of scope. |
| Observability | None required. | Errors are logged. | Structured logs and error tracking. | Metrics, dashboards, and alerts. |
| Performance | Fast enough to demo. | Usable for real work. | Checked at realistic volumes. | Meets agreed targets at peak load. |
| Security and privacy | No secrets or client data. | Full standard once it touches client systems. | Dependencies scanned, inputs hardened. | Reviewed where it matters most. |
| Data and migrations | Sample data, clearly marked. | Migrations, and data that can be cleaned up. | Validated, with reversible migrations. | Tested migrations and tested restores. |
| User experience | Shows the idea. | The main workflow works end to end. | Loading, empty, and error states. | Consistent, accessible, and polished. |
| Documentation | What it shows and what it doesn't. | How to try it. | How to use it, and what may change. | Complete, with a changelog. |
| Release and operations | Outside production. | Behind a flag, with a badge. | Normal pipeline, with a badge. | No badge, with a tested rollback. |
| Breaking changes | Anything goes. | Allowed, and noted. | Avoided, and announced first. | Only in a new version. |
How to use the checklists
- Use your judgment. An item that doesn't apply, such as user experience for a background job, doesn't apply. If an item does apply and isn't met, mention it to the client so there are no surprises.
- Each level includes everything below it, except where a higher level replaces an item, such as the Beta badge replacing the Alpha one. Items new at a level are in bold, and each item's icon shows the level that introduced it.
- Paste a checklist into a pull request if it helps, for example when moving a larger feature to GA. Each tab has a markdown version.
- Reviewers use the label to calibrate. Don't ask for GA polish on a prototype, and don't wave through prototype shortcuts in GA work.
- Work on something already GA meets the GA checklist for the part it changes, including bug fixes.
Security, the privacy of client data, and the commercial rules apply at every level. The security items start at Alpha because that's usually when work first touches client systems. A prototype that touches client data or credentials meets them too.
The checklists
- Prototype
- Alpha
- Beta
- GA
Code structure
- Kept apart from production code: its own branch, folder, or feature flag.
Tests
- The path you'll demo works, checked by hand.
Edge cases and errors
- Known gaps are written down, so no one mistakes them for bugs.
Observability
Nothing required at this level.
Performance
- Fast enough that the demo makes its point.
Security and privacy
- No secrets or real client data in the code, mocks, screenshots, or demos.
Data and migrations
- Mock or sample data is clearly marked as such.
User experience
- Shows the idea clearly enough to react to.
Documentation
- A note on the question it answers, what's mocked, and what doesn't work.
Release and operations
- Runs outside production, or behind a feature flag that's off by default.
Breaking changes
Nothing required at this level.
Markdown for a pull request description
## Stability checklist: Prototype
**Code structure**
- [ ] Kept apart from production code: its own branch, folder, or feature flag.
**Tests**
- [ ] The path you'll demo works, checked by hand.
**Edge cases and errors**
- [ ] Known gaps are written down, so no one mistakes them for bugs.
**Performance**
- [ ] Fast enough that the demo makes its point.
**Security and privacy**
- [ ] No secrets or real client data in the code, mocks, screenshots, or demos.
**Data and migrations**
- [ ] Mock or sample data is clearly marked as such.
**User experience**
- [ ] Shows the idea clearly enough to react to.
**Documentation**
- [ ] A note on the question it answers, what's mocked, and what doesn't work.
**Release and operations**
- [ ] Runs outside production, or behind a feature flag that's off by default.
Code structure
- Follows the project's conventions and passes lint and type checks.
- Reviewed by another engineer before merging.
- The parts most likely to change are easy to change, with no speculative abstractions.
Tests
- An automated test covers the main path.
Edge cases and errors
- Known gaps are written down, so no one mistakes them for bugs.
- Errors fail visibly: no swallowed exceptions or silently dropped data.
- Input is validated where real data enters the system.
Observability
- Errors are logged with enough context to reproduce them, and without secrets or personal data.
Performance
- Usable for the real work it's meant for, at today's scale.
Security and privacy
- No secrets or real client data in the code, mocks, screenshots, or demos.
- Authentication and authorization are enforced on everything that touches client systems or data.
- Secrets live in the project's secret store, not in code or config.
- Personal data is collected only where the feature needs it.
Data and migrations
- Mock or sample data is clearly marked as such.
- Schema changes are migrations, not manual edits.
- Real data it creates can be fixed or cleaned up if the design changes.
User experience
- A real user can complete the main workflow end to end.
Documentation
- How to try it, and what's known to be missing or broken.
Release and operations
- Behind a feature flag, with an Alpha badge wherever people see it.
Breaking changes
- Breaking changes are noted in the pull request.
Markdown for a pull request description
## Stability checklist: Alpha
**Code structure**
- [ ] Follows the project's conventions and passes lint and type checks.
- [ ] Reviewed by another engineer before merging.
- [ ] The parts most likely to change are easy to change, with no speculative abstractions.
**Tests**
- [ ] An automated test covers the main path.
**Edge cases and errors**
- [ ] Known gaps are written down, so no one mistakes them for bugs.
- [ ] Errors fail visibly: no swallowed exceptions or silently dropped data.
- [ ] Input is validated where real data enters the system.
**Observability**
- [ ] Errors are logged with enough context to reproduce them, and without secrets or personal data.
**Performance**
- [ ] Usable for the real work it's meant for, at today's scale.
**Security and privacy**
- [ ] No secrets or real client data in the code, mocks, screenshots, or demos.
- [ ] Authentication and authorization are enforced on everything that touches client systems or data.
- [ ] Secrets live in the project's secret store, not in code or config.
- [ ] Personal data is collected only where the feature needs it.
**Data and migrations**
- [ ] Mock or sample data is clearly marked as such.
- [ ] Schema changes are migrations, not manual edits.
- [ ] Real data it creates can be fixed or cleaned up if the design changes.
**User experience**
- [ ] A real user can complete the main workflow end to end.
**Documentation**
- [ ] How to try it, and what's known to be missing or broken.
**Release and operations**
- [ ] Behind a feature flag, with an Alpha badge wherever people see it.
**Breaking changes**
- [ ] Breaking changes are noted in the pull request.
Code structure
- Follows the project's conventions and passes lint and type checks.
- Reviewed by another engineer before merging.
- The parts most likely to change are easy to change, with no speculative abstractions.
- Business logic is separate from the UI, storage, and external services.
- Shortcuts from earlier levels are removed, or tracked as issues.
Tests
- An automated test covers the main path.
- Tests cover known edge cases and error paths.
- Tests run in CI on every pull request and block merging when they fail.
Edge cases and errors
- Known gaps are written down, so no one mistakes them for bugs.
- Errors fail visibly: no swallowed exceptions or silently dropped data.
- Input is validated where real data enters the system.
- Empty, missing, duplicate, and unusually large inputs are handled.
- Calls to external services have timeouts, and retries where they're safe.
- People see a helpful message when something fails, not a stack trace.
Observability
- Errors are logged with enough context to reproduce them, and without secrets or personal data.
- Key actions write structured logs.
- Errors are reported to the project's error tracker.
- Services have a health check.
Performance
- Usable for the real work it's meant for, at today's scale.
- Tried with realistic data volumes, and lists and queries are paginated or bounded.
- Obvious problems are fixed, such as repeated queries in a loop, missing indexes, and oversized payloads.
Security and privacy
- No secrets or real client data in the code, mocks, screenshots, or demos.
- Authentication and authorization are enforced on everything that touches client systems or data.
- Secrets live in the project's secret store, not in code or config.
- Personal data is collected only where the feature needs it.
- Inputs are protected against injection and cross-site scripting.
- Dependencies are scanned, with no known high-severity vulnerabilities.
Data and migrations
- Mock or sample data is clearly marked as such.
- Schema changes are migrations, not manual edits.
- Real data it creates can be fixed or cleaned up if the design changes.
- Data is validated before it's written.
- Migrations are reversible, or have a tested backup to restore from.
User experience
- A real user can complete the main workflow end to end.
- Loading, empty, and error states are designed, not left blank.
- Works with a keyboard, with labeled controls and readable contrast.
Documentation
- How to use and configure it, and what may still change.
Release and operations
- Deployed through the normal pipeline, not by hand.
- A Beta badge wherever people see it.
- Can be turned off or rolled back without a code change.
Breaking changes
- Breaking changes are noted in the pull request.
- Breaking changes are avoided. When one is needed, the client hears first, with migration notes.
Markdown for a pull request description
## Stability checklist: Beta
**Code structure**
- [ ] Follows the project's conventions and passes lint and type checks.
- [ ] Reviewed by another engineer before merging.
- [ ] The parts most likely to change are easy to change, with no speculative abstractions.
- [ ] Business logic is separate from the UI, storage, and external services.
- [ ] Shortcuts from earlier levels are removed, or tracked as issues.
**Tests**
- [ ] An automated test covers the main path.
- [ ] Tests cover known edge cases and error paths.
- [ ] Tests run in CI on every pull request and block merging when they fail.
**Edge cases and errors**
- [ ] Known gaps are written down, so no one mistakes them for bugs.
- [ ] Errors fail visibly: no swallowed exceptions or silently dropped data.
- [ ] Input is validated where real data enters the system.
- [ ] Empty, missing, duplicate, and unusually large inputs are handled.
- [ ] Calls to external services have timeouts, and retries where they're safe.
- [ ] People see a helpful message when something fails, not a stack trace.
**Observability**
- [ ] Errors are logged with enough context to reproduce them, and without secrets or personal data.
- [ ] Key actions write structured logs.
- [ ] Errors are reported to the project's error tracker.
- [ ] Services have a health check.
**Performance**
- [ ] Usable for the real work it's meant for, at today's scale.
- [ ] Tried with realistic data volumes, and lists and queries are paginated or bounded.
- [ ] Obvious problems are fixed, such as repeated queries in a loop, missing indexes, and oversized payloads.
**Security and privacy**
- [ ] No secrets or real client data in the code, mocks, screenshots, or demos.
- [ ] Authentication and authorization are enforced on everything that touches client systems or data.
- [ ] Secrets live in the project's secret store, not in code or config.
- [ ] Personal data is collected only where the feature needs it.
- [ ] Inputs are protected against injection and cross-site scripting.
- [ ] Dependencies are scanned, with no known high-severity vulnerabilities.
**Data and migrations**
- [ ] Mock or sample data is clearly marked as such.
- [ ] Schema changes are migrations, not manual edits.
- [ ] Real data it creates can be fixed or cleaned up if the design changes.
- [ ] Data is validated before it's written.
- [ ] Migrations are reversible, or have a tested backup to restore from.
**User experience**
- [ ] A real user can complete the main workflow end to end.
- [ ] Loading, empty, and error states are designed, not left blank.
- [ ] Works with a keyboard, with labeled controls and readable contrast.
**Documentation**
- [ ] How to use and configure it, and what may still change.
**Release and operations**
- [ ] Deployed through the normal pipeline, not by hand.
- [ ] A Beta badge wherever people see it.
- [ ] Can be turned off or rolled back without a code change.
**Breaking changes**
- [ ] Breaking changes are noted in the pull request.
- [ ] Breaking changes are avoided. When one is needed, the client hears first, with migration notes.
Code structure
- Follows the project's conventions and passes lint and type checks.
- Reviewed by another engineer before merging.
- The parts most likely to change are easy to change, with no speculative abstractions.
- Business logic is separate from the UI, storage, and external services.
- Shortcuts from earlier levels are removed, or tracked as issues.
- Another engineer can change it without the author: clear names, small modules, and comments where the reason isn't obvious.
- No untracked TODOs, dead code, or leftover prototype paths.
Tests
- An automated test covers the main path.
- Tests cover known edge cases and error paths.
- Tests run in CI on every pull request and block merging when they fail.
- Every critical workflow has an integration or end-to-end test.
- Every fixed bug has a regression test.
- No flaky or skipped tests without an issue to fix them.
Edge cases and errors
- Known gaps are written down, so no one mistakes them for bugs.
- Errors fail visibly: no swallowed exceptions or silently dropped data.
- Input is validated where real data enters the system.
- Empty, missing, duplicate, and unusually large inputs are handled.
- Calls to external services have timeouts, and retries where they're safe.
- People see a helpful message when something fails, not a stack trace.
- Concurrent use and partial failures are handled, and anything that can be retried is safe to repeat.
- Every known edge case is handled, or documented as out of scope with the client's agreement.
Observability
- Errors are logged with enough context to reproduce them, and without secrets or personal data.
- Key actions write structured logs.
- Errors are reported to the project's error tracker.
- Services have a health check.
- Key workflows have metrics for volume, errors, and duration, on a dashboard.
- Failures people would notice raise an alert, routed to whoever operates production.
- Each alert has a note on what it means and what to do.
Performance
- Usable for the real work it's meant for, at today's scale.
- Tried with realistic data volumes, and lists and queries are paginated or bounded.
- Obvious problems are fixed, such as repeated queries in a loop, missing indexes, and oversized payloads.
- Meets the performance targets agreed with the client, measured rather than assumed.
- Handles expected peak load with room to spare.
Security and privacy
- No secrets or real client data in the code, mocks, screenshots, or demos.
- Authentication and authorization are enforced on everything that touches client systems or data.
- Secrets live in the project's secret store, not in code or config.
- Personal data is collected only where the feature needs it.
- Inputs are protected against injection and cross-site scripting.
- Dependencies are scanned, with no known high-severity vulnerabilities.
- Anything handling sign-in, payments, or personal data has had a security review by a second engineer.
- Access follows least privilege, and sensitive actions leave an audit trail.
Data and migrations
- Mock or sample data is clearly marked as such.
- Schema changes are migrations, not manual edits.
- Real data it creates can be fixed or cleaned up if the design changes.
- Data is validated before it's written.
- Migrations are reversible, or have a tested backup to restore from.
- Migrations have been run against a production-sized copy of the data.
- Backups are in place, and restoring from one has been tested.
User experience
- A real user can complete the main workflow end to end.
- Loading, empty, and error states are designed, not left blank.
- Works with a keyboard, with labeled controls and readable contrast.
- Consistent with the rest of the product, on the browsers and devices agreed with the client.
- Meets the accessibility standard agreed with the client.
Documentation
- User and developer documentation is complete and current.
- Public interfaces, such as APIs, have reference documentation.
- The release has a changelog entry.
Release and operations
- Deployed through the normal pipeline, not by hand.
- Badge removed, and the feature flag removed or permanently on.
- Rollback has been tested, and whoever operates production knows the feature exists.
Breaking changes
- Breaking changes are noted in the pull request.
- Public interfaces, such as APIs, exports, file formats, and workflows, are documented as stable.
- Breaking changes are made only in a new version.
Markdown for a pull request description
## Stability checklist: GA
**Code structure**
- [ ] Follows the project's conventions and passes lint and type checks.
- [ ] Reviewed by another engineer before merging.
- [ ] The parts most likely to change are easy to change, with no speculative abstractions.
- [ ] Business logic is separate from the UI, storage, and external services.
- [ ] Shortcuts from earlier levels are removed, or tracked as issues.
- [ ] Another engineer can change it without the author: clear names, small modules, and comments where the reason isn't obvious.
- [ ] No untracked TODOs, dead code, or leftover prototype paths.
**Tests**
- [ ] An automated test covers the main path.
- [ ] Tests cover known edge cases and error paths.
- [ ] Tests run in CI on every pull request and block merging when they fail.
- [ ] Every critical workflow has an integration or end-to-end test.
- [ ] Every fixed bug has a regression test.
- [ ] No flaky or skipped tests without an issue to fix them.
**Edge cases and errors**
- [ ] Known gaps are written down, so no one mistakes them for bugs.
- [ ] Errors fail visibly: no swallowed exceptions or silently dropped data.
- [ ] Input is validated where real data enters the system.
- [ ] Empty, missing, duplicate, and unusually large inputs are handled.
- [ ] Calls to external services have timeouts, and retries where they're safe.
- [ ] People see a helpful message when something fails, not a stack trace.
- [ ] Concurrent use and partial failures are handled, and anything that can be retried is safe to repeat.
- [ ] Every known edge case is handled, or documented as out of scope with the client's agreement.
**Observability**
- [ ] Errors are logged with enough context to reproduce them, and without secrets or personal data.
- [ ] Key actions write structured logs.
- [ ] Errors are reported to the project's error tracker.
- [ ] Services have a health check.
- [ ] Key workflows have metrics for volume, errors, and duration, on a dashboard.
- [ ] Failures people would notice raise an alert, routed to whoever operates production.
- [ ] Each alert has a note on what it means and what to do.
**Performance**
- [ ] Usable for the real work it's meant for, at today's scale.
- [ ] Tried with realistic data volumes, and lists and queries are paginated or bounded.
- [ ] Obvious problems are fixed, such as repeated queries in a loop, missing indexes, and oversized payloads.
- [ ] Meets the performance targets agreed with the client, measured rather than assumed.
- [ ] Handles expected peak load with room to spare.
**Security and privacy**
- [ ] No secrets or real client data in the code, mocks, screenshots, or demos.
- [ ] Authentication and authorization are enforced on everything that touches client systems or data.
- [ ] Secrets live in the project's secret store, not in code or config.
- [ ] Personal data is collected only where the feature needs it.
- [ ] Inputs are protected against injection and cross-site scripting.
- [ ] Dependencies are scanned, with no known high-severity vulnerabilities.
- [ ] Anything handling sign-in, payments, or personal data has had a security review by a second engineer.
- [ ] Access follows least privilege, and sensitive actions leave an audit trail.
**Data and migrations**
- [ ] Mock or sample data is clearly marked as such.
- [ ] Schema changes are migrations, not manual edits.
- [ ] Real data it creates can be fixed or cleaned up if the design changes.
- [ ] Data is validated before it's written.
- [ ] Migrations are reversible, or have a tested backup to restore from.
- [ ] Migrations have been run against a production-sized copy of the data.
- [ ] Backups are in place, and restoring from one has been tested.
**User experience**
- [ ] A real user can complete the main workflow end to end.
- [ ] Loading, empty, and error states are designed, not left blank.
- [ ] Works with a keyboard, with labeled controls and readable contrast.
- [ ] Consistent with the rest of the product, on the browsers and devices agreed with the client.
- [ ] Meets the accessibility standard agreed with the client.
**Documentation**
- [ ] User and developer documentation is complete and current.
- [ ] Public interfaces, such as APIs, have reference documentation.
- [ ] The release has a changelog entry.
**Release and operations**
- [ ] Deployed through the normal pipeline, not by hand.
- [ ] Badge removed, and the feature flag removed or permanently on.
- [ ] Rollback has been tested, and whoever operates production knows the feature exists.
**Breaking changes**
- [ ] Breaking changes are noted in the pull request.
- [ ] Public interfaces, such as APIs, exports, file formats, and workflows, are documented as stable.
- [ ] Breaking changes are made only in a new version.
Frequently asked questions
Do I need approval to move something up a level?
No. Move it when it's ready, and tell the client. Check with them first only when the move changes what they or their users rely on, such as trying it with real users or calling it GA.
Do I have to meet every checklist item before moving up?
No. The checklists are what's typical, not a gate. Use them to judge whether something is ready, and if an item that matters isn't met, tell the client so they can weigh it.
Can a feature move through several levels in one block?
Yes. Prototype in the morning and Alpha by the afternoon is fine, and so is Prototype to GA within one iteration if the client is happy and the work is ready. See Moving between levels for an example.
Who agrees performance targets and supported browsers for GA?
The client, ideally before the feature reaches GA. Suggest targets based on how the feature is used, and write them down on the issue.
Who operates the alerts a GA feature needs?
Whoever operates production. On Exalynt Managed, that's Exalynt. On Self Managed, alerts go to the client's team, so agree where they go before GA.
Can the checklists change?
Yes. They live in src/data/stability-checklist.ts. If an item never seems to matter, or a gap keeps causing problems, propose a change so the checklist reflects how we actually work.