Skip to content

Deploying

We pick hosting to suit each project. Our usual choices are:

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.

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.

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 staging branch automatically deploys the staging application.
  • The production branch 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:

  1. Open a pull request from main to production. 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.
  2. Let the project team know on Slack you’re preparing a deploy.
  3. 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.
  4. Wait for CI to pass the commit you’re merging.
  5. Merge the PR.
  6. Wait for CI to pass the merge commit (you can watch this on GitHub).
  7. 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.

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.

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_

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:

  1. 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.
  2. 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.
  3. Use the PR’s preview environment. If the project has one, try the change there before it’s merged.
  4. 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 to main as soon as you’re done.