The CTO's Playbook for a Release Process That Actually Works
If your release process is "merge to main and see what happens," you are not alone. Most engineering teams at the sub-$10M ARR stage are running some version of this playbook, and for a brief window it actually works. Then the team grows, the codebase deepens, and a release that used to feel routine suddenly becomes a two-hour incident postmortem. A deliberate release process is not bureaucracy. It is the infrastructure that lets you ship confidently at speed.
Where most startups begin
Stage 0 looks roughly like this: a developer finishes a feature, runs the app locally to confirm it loads, and pushes straight to the deployment branch. Testing is whatever the developer happened to click through before committing. The staging environment, if one exists, is either out of date or ignored. Hope is the primary quality gate.
This works at three engineers shipping to fifty users. It stops working the moment the feature surface grows beyond what one person can hold in their head. The first sign that Stage 0 has expired is usually a regression in a feature nobody touched, introduced by a change in shared state that nobody tracked.
The honest diagnosis is not that the team was careless. It is that the process never scaled to match the complexity of the product.
Stage 1: getting a basic pipeline in place
The first upgrade is mechanical. Set up continuous integration so that every pull request runs your test suite before it can merge. Add a staging environment that receives deployments automatically after the CI checks pass. Designate one person each release cycle to click through the critical paths on staging before anything goes to production.
This sounds simple because it is. The value is not in the sophistication of the setup. It is in the forcing function: code cannot reach production without passing at least a baseline check. That single constraint catches a meaningful share of regressions before customers ever see them.
A minimal GitHub Actions configuration that covers the basics looks like this:
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npm test
- name: Deploy to staging
if: github.ref == 'refs/heads/main'
run: ./scripts/deploy-staging.shStage 1 does not require a QA hire. It requires thirty minutes to wire up a pipeline and the discipline to actually review what staging shows you. Most teams can reach Stage 1 in an afternoon.
Stage 2: structured QA before every release
Stage 2 is where a release process starts to feel like a real process. The difference from Stage 1 is intentionality. Testing on staging is no longer informal clicking. It follows a documented test plan that covers the changes in the current release plus the critical paths that must not regress.
The test plan does not need to be elaborate. A shared document or ticket template that lists the areas to exercise and the expected outcomes is enough to start. What matters is that someone reviews it before the release begins and signs off before production is touched.
This sign-off is the go/no-go decision. It sounds formal, but in practice it can be a single Slack message from the designated reviewer saying "staging looks good, clear to ship." The ritual creates accountability that ad hoc testing never does. You can read more about building systematic confidence in the companion post on moving from staging to production with a confidence checklist.
Stage 2 is also when teams commonly introduce their first dedicated testing resource, whether that is a QA engineer, a contracted tester, or a managed QA service. Exploratory coverage from a person who did not write the code surfaces a different category of defect than automated checks alone. That asymmetry is worth understanding before you decide how to staff it.
One thing Stage 2 teams consistently underestimate is test plan scope. A release that touches the payment flow should test the full checkout path, not just the changed component. Regressions almost never appear exactly where the change was made. They appear in the adjacent code that shares state, configuration, or a database table with the changed component. A test plan that only covers the diff misses the blast radius.
Stage 3: automated gates, human verification, and rollback readiness
A mature release process has three properties that earlier stages lack: automated quality gates that block deployment on failure, human QA coverage on every release rather than selected ones, and a tested rollback procedure that the team can execute without reading a wiki page for the first time under pressure.
Automated gates are not a replacement for human judgment. They are the floor. A gate that blocks a deploy when the smoke test suite fails means that obvious regressions never reach production, freeing your QA coverage to focus on the subtle, context-dependent issues that automation cannot find. For a deeper look at how automation and manual testing divide the work, the post on adding QA to your CI/CD pipeline without slowing releases walks through the tradeoffs in practical terms.
The rollback plan is the piece most teams defer until they need it. Define it before the next release, not during an incident. At minimum, this means knowing the command to revert a deployment, verifying that database migrations can be rolled back safely, and confirming who is authorized to pull the trigger without needing approval from three people who are asleep.
Communication at Stage 3 also becomes more structured. Release notes sent to a shared channel before deployment, status updates during the deploy window, and a brief retrospective after any held release create a feedback loop that sharpens the process over time. Teams that skip this communication layer often find that their release process exists only in the heads of two or three engineers, which creates a fragile single point of failure.
The four ingredients every release process needs
Regardless of which stage you are at, four elements separate a release process that works from one that eventually fails you:
- A staging environment that mirrors production. Staging that diverges from production in data shape, configuration, or dependency versions gives you false confidence. Bugs that only surface in production are often staging fidelity problems in disguise.
- A defined QA checkpoint. Someone must own the decision to ship. That ownership needs to be explicit, not assumed. A rotating on-call role, a named release captain, or a structured sign-off document all work. Ambiguity does not.
- A rollback plan you have actually tested. A rollback procedure you have never rehearsed is a theory. Run a drill quarterly. Confirm that the steps still work and that more than one engineer knows how to execute them.
- A communication protocol. When a release goes out, who knows? When a release is held, who gets notified and why? Customer support, success, and product stakeholders operate better when release status is shared proactively. Even a brief Slack post to a #releases channel reduces incident response time when something goes wrong.
Getting there without rebuilding everything at once
You do not need to jump from Stage 0 to Stage 3 over a single sprint. That kind of big-bang process change almost always stalls because it asks too much of the team simultaneously. Incremental maturity is more durable because each addition builds on what already exists rather than replacing it.
A realistic sequence looks like this. In week one, wire up CI so that tests run on every pull request. In week two, create a staging environment and route your main branch deploys there automatically. In week three, write a one-page test plan template and designate a release reviewer for your next planned release. In week four, run the go/no-go for real and document what you learned.
By the end of that month, you have covered Stages 1 and 2 without disrupting the team's existing cadence. Stage 3 can follow as the team develops appetite for the additional rigor. The goal is forward motion, not perfection. Shipping quality software at speed is itself a compounding process, as explored in the post on how fast-growing teams maintain quality without slowing down.
The teams that struggle are not the ones that move slowly through these stages. They are the ones that skip stages and then spend their engineering bandwidth paying the interest on that debt. Each escaped defect, each production incident, each unplanned rollback represents capacity that was not available for the roadmap. The release process is not overhead. It is what lets the roadmap move.
If you are ready to add structured QA coverage to your releases but are not sure whether an internal hire or an external model fits better, Pinpoint's managed QA approach is designed specifically for teams at this stage. It pairs QA engineers with your existing pipeline rather than asking you to rebuild the process from scratch.
Ready to level up your QA?
Book a free 30-minute call and see how Pinpoint plugs into your pipeline with zero overhead.