Deploying
Hosting
Section titled “Hosting”We pick hosting to suit each project. Our usual choices are:
- Vercel or Cloudflare Workers for web front ends and agents.
- AWS ECS or Azure Container Apps for containerised apps. The client’s cloud usually decides which.
- Render for straightforward Rails apps.
- Terraform to manage infrastructure as code.
Deployment process
Section titled “Deployment process”You wrote it, you deploy it
Section titled “You wrote it, you deploy it”Whoever wrote a change deploys it, watches it go out, and rolls it back if something goes wrong. This applies to client developers and other agencies working on the same codebase as much as it does to us.
Handing deploys to a particular person or team pulls them out of context and slows everyone down. The author knows best what the change does, what to watch for, and what “working” looks like.
This doesn’t change how we support a project. Our support process is the same no matter who wrote the code, so us doing every deploy wouldn’t make support any easier.
Nothing sits on main undeployed
Section titled “Nothing sits on main undeployed”If it’s on main, it’s ready for production. This is what makes “you wrote
it, you deploy it” work: you’re never blocked from deploying your change
because someone else’s half-finished work is sitting on main ahead of it.
Anything that isn’t ready for users goes behind a feature flag, or waits on its branch. See testing risky changes on staging.
How to deploy
Section titled “How to deploy”Anything on main can be deployed at any time. Most projects have a staging
and a production environment, each deployed from its own branch:
- The
stagingbranch automatically deploys the staging application. - The
productionbranch automatically deploys the production application.
Our gold standard is a preview environment for every pull request, so you can try a change out before it’s merged.
To deploy to staging, open a pull request from main to staging. A deploy to
production is then:
- Open a pull request from
maintoproduction. Title it with the date & ‘production deploy’. Use the template below. Detail in the PR description what is going to be deployed. Check through the diff for any tasks that need to be run manually e.g. one-off rake tasks, and document them in the description too so you don’t forget. - Let the project team know on Slack you’re preparing a deploy.
- Before deploying, liaise with another developer on the project to ensure there are no impending merges that might conflict with your deployment. This step helps to mitigate the risk of simultaneous merges, especially from main to production, that might inadvertently escalate the scope of deployment.
- Wait for CI to pass the commit you’re merging.
- Merge the PR.
- Wait for CI to pass the merge commit (you can watch this on GitHub).
- Once CI passes the merge commit, the deploy should start. Watch it go out in your project’s pipeline, such as GitHub Actions, Vercel or Cloudflare.
Once deployment finishes, let the project team know it’s live and run any one-off tasks you documented at the start of the process.
Release notes
Section titled “Release notes”Whenever you deploy to production, post a couple of sentences in the client’s shared Slack channel saying what’s going out. Write for everyone with a stake in the project, not just developers: the client’s product team, their developers, and any other agencies we work alongside.
This means everyone knows what’s changed without needing eyes on every deploy. It also gives whoever is on support a record to check when something breaks. The deploy PR description is a good starting point.
PR template
Section titled “PR template”This template is loosely based on Keep a Changelog
_Delete any empty headings_
### Added_New features._
### Changed_Changes in existing functionality._
### Deprecated_Soon-to-be removed features._
### Removed_Now removed features._
### Fixed_Any bug fixes._
### Security_Any vulnerabilities fixed_
### Deployment notes_Any steps that need to be performed as part of deployment e.g. rake tasks_Testing risky changes on staging
Section titled “Testing risky changes on staging”Because anything on main is ready for production, you need another way to
try out a breaking or unfinished change on staging. In order of preference:
- Break the work into vertical slices. A vertical slice is a small, complete piece of functionality that works end to end, from the database to the UI. Small slices mean small deploys, and nothing half-finished to hold back. Most of the time this removes the need for anything else on this list. See estimating for how we break stories down.
- Put anything risky or partial behind a feature flag. This separates deploying the code from switching the change on, so you can turn it on in staging and leave it off in production. See fast, continuous(-ish) deployment.
- Use the PR’s preview environment. If the project has one, try the change there before it’s merged.
- Merge a feature branch straight into staging. This is a last resort.
We’ve seen it slow teams down many times, because it gets hard to track
what’s on staging, what’s on
main, and what’s in production. If you do it, tell the team, and reset staging back tomainas soon as you’re done.