Skip to content
Proudly based in Nova Scotia, Canada · clients welcome from every countryContact usClient login
CodeLumaDevelopment Inc.

Home / Blog / Article

CodeLuma insights · May 7, 2026 · 7 min read

Zero-Downtime Deployments: Why Your Users Should Never See "Maintenance Mode"

How to release software without interrupting service: rolling, blue-green and canary deployments, backwards-compatible database migrations, health checks, feature flags, rollback plans and sessions that survive a release.

There is a familiar ritual in many organisations: announce a maintenance window for late Saturday night, put up a "we will be back soon" page, deploy, test nervously and hope. Customers are inconvenienced, engineers are tired, and the fear of releases means they happen rarely, which makes each one bigger and riskier. Zero-downtime deployment breaks that cycle. With the right techniques, you can release changes during business hours, in small increments, and roll back in seconds if something is wrong. This guide explains how.

Several strategies achieve zero downtime; many teams combine them.
Several strategies achieve zero downtime; many teams combine them.

Why downtime during deployment is optional

Downtime during releases usually comes from three causes: stopping the old version before the new one is ready, changes that are incompatible with what is currently running, and slow, manual processes. Each has a solution. Run multiple instances behind a load balancer so some are always available, keep changes backwards-compatible so old and new versions can coexist, and automate everything so releases are quick and consistent. The business benefits are large: faster feedback, fewer big-bang failures, happier customers, and the freedom to fix problems immediately.

Network cables plugged into a switch
Original CodeLuma 3D render: network cables plugged into a switch.

Rolling deployments

In a rolling deployment, you update instances gradually. The load balancer takes one server out of rotation, the new version is deployed and health-checked, it rejoins, and then the next is updated. At every moment, enough capacity serves traffic. It is simple and supported by most platforms. The main consideration is that during the rollout, both versions serve requests simultaneously, so they must be compatible, especially at the database level and in any shared caches, queues or APIs.

Blue-green deployments

Blue-green maintains two identical environments: one live and one idle. You deploy the new version to the idle environment, run smoke tests against it, then switch the router so all traffic goes to the new one. If problems appear, switching back takes seconds. The cost is running double capacity during the deployment window, which cloud platforms make affordable because the idle environment can be temporary. Blue-green shines for high-stakes releases, though database changes still require the compatibility discipline described below.

Canary releases

A canary release sends a small fraction of real traffic, perhaps one to five percent, to the new version, while monitoring error rates, latency and business metrics. If everything looks healthy, the percentage increases in stages; if not, traffic reverts. Canaries limit the blast radius of undetected problems, and are especially valuable for changes that are hard to test fully in staging, such as performance-sensitive code. They depend on strong monitoring; see our guide to application monitoring.

Feature flags: separate deployment from release

Feature flags let you deploy code with new functionality turned off, then enable it for specific users, teams or a percentage, independently of the deployment. If something goes wrong, you switch the flag off without redeploying. Flags also enable dark launches, gradual rollouts and A/B tests. They require discipline: name flags clearly, assign owners, and remove them once the feature is fully released, or the code fills with dead branches. We explore this technique further in our feature flags article.

The hardest part: the database

Application code is easy to swap; databases hold state and cannot be duplicated freely. The key technique is the expand-and-contract, or parallel change, pattern. Never make a change that breaks the version of the code currently running.

  1. Expand. Add new columns or tables without removing anything. New columns should be nullable or have defaults so old code that ignores them keeps working.
  2. Deploy code that supports both structures, writing to old and new as needed and reading from the old.
  3. Backfill existing data into the new structure in small batches, throttled to avoid locking or overloading the database.
  4. Switch reads to the new structure after verifying the data matches.
  5. Contract. In a later release, once no running code uses the old columns, drop them.

Avoid operations that lock large tables for long periods, such as adding a non-null column with a default on some engines or building indexes without online options. Test migrations against production-sized data. Renaming a column is really an add, copy, switch and drop sequence. Migrations should run as a separate, controlled step in the pipeline, be idempotent and have a plan for failure.

Backwards-compatible database migrations let old and new code run against the same database during a release.
Backwards-compatible database migrations let old and new code run against the same database during a release.

Health checks and graceful shutdown

Load balancers need to know when an instance is ready and when it is not. Implement health endpoints that verify the application can actually serve requests, including dependencies where appropriate, and distinguish liveness, meaning the process is running, from readiness, meaning it can take traffic. On shutdown, instances should stop accepting new connections, finish in-flight requests within a time limit, close connections cleanly and exit. Configure the platform to wait for that drain period before terminating. Without graceful shutdown, users experience dropped requests and failed uploads during every deploy.

Handle sessions, caches and in-flight work

  • Sessions. Store them in a shared store such as a cache or database, not in server memory, so users stay logged in as instances change. See our scalable architecture guide.
  • Cached data. Make cached structures compatible across versions, or include a version in cache keys so old and new do not confuse each other.
  • Background jobs and queues. Ensure workers can process messages produced by both versions, and drain or pause workers gracefully. Use versioned message schemas.
  • Static assets. Use fingerprinted file names and keep old assets available briefly so pages loaded before the deployment can still fetch their scripts. Otherwise users with open tabs see errors.
  • APIs. Keep API changes backwards-compatible for clients that update on a different schedule, particularly mobile apps.
A laptop showing source code on a desk
Original CodeLuma 3D render: a laptop showing source code on a desk.

Automate the pipeline

Zero-downtime releases depend on a reliable, automated path from commit to production: build once, run automated tests, deploy to staging, run smoke tests, deploy to production using the chosen strategy, verify health and roll back automatically when checks fail. Keep the process identical every time so it is practised constantly. Our article on CI/CD pipelines describes what to include, and infrastructure as code keeps the environments consistent.

Plan for rollback

Every deployment needs a way back. For code, that means keeping the previous artefact and being able to redeploy or switch to it quickly. Database changes are harder: because expand-and-contract keeps the old structure until later, code rollbacks remain safe. Decide in advance who can trigger a rollback, what conditions call for one and how you will communicate. Practise it. A rollback you have never tested is not a plan.

Watch the release

Deployments are risky moments. Add release markers to dashboards so changes correlate with metrics, watch error rates, latency, and key business events such as sign-ups and orders for the first minutes, and use automated analysis to halt canaries on regression. After incidents, review the process rather than blaming individuals.

Cultural and practical benefits

Small, frequent releases are easier to understand, test and reverse than large infrequent ones. When deployment is routine, teams ship improvements more quickly, fix defects sooner and take fewer risks per release. Customers stop seeing maintenance pages, and engineers stop dreading release night.

Where to start

If you currently take the site down to deploy, begin by running at least two instances behind a load balancer, adding health checks and graceful shutdown, making database migrations backwards-compatible, and automating the pipeline. Then add blue-green or canary options for higher-risk changes. Our hosting and software teams build these pipelines routinely, and can take you from Saturday-night releases to confident mid-week ones.


Put this into practice with CodeLuma

CodeLuma sets up deployment pipelines that ship changes without downtime, using rolling and blue-green releases, safe database migrations and instant rollback, so releasing on a Tuesday afternoon is boring.

Start a conversation. Tell us about your project and we will reply with practical next steps, or browse all CodeLuma services. CodeLuma Development Inc. is based in Nova Scotia and works with teams across Canada and remotely.

Keep reading

Share this article: Facebook · LinkedIn · X · Email

← All articles

Ready to put this into practice?

Talk to a Nova Scotia full-stack team that builds complex, connected systems for clients across Canada and worldwide.

Start a project