Zero-downtime deployment C#: updating a service without downtime

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Why your service shouldn't "go down for lunch"?



Imagine: Friday, 6:45 PM. You've just launched a long-awaited update to your C# service. And immediately, messages fly into the support chat: "site not working", "error 503", "lost cart data". Sound familiar? This is the classic scenario where a "kick-in-the-door" deployment kills the user experience. In today's world, where every hour of downtime can cost millions, zero-downtime deployment of C# services is not a luxury, but a basic development hygiene.



In this article, we won't give boring lectures. We'll break down real strategies for updating .NET applications without stopping work, write code for health checks and graceful shutdown, and show how to configure rolling updates in Kubernetes. If you're tired of "magical" production crashes after every commit — this material is for you. Let's go!



What is zero-downtime deployment and why does a C# developer need it?



Zero-downtime deployment is a technique for updating an application where the old version continues to serve requests until the new version is fully operational. The user doesn't notice the switch: no errors, no timeouts, no session loss.



Main problems when updating C# services

  • Graceful shutdown doesn't always work. The standard app.StopAsync() can terminate active requests if timeouts aren't configured.
  • Stuck connections. The old version holds open WebSocket or long HTTP requests.
  • Database migrations. The new version requires schema changes that the old version is incompatible with.
  • Cache and sessions. After the switch, the user loses in-memory data.


The good news: C# and the .NET ecosystem provide all the tools to solve these problems. Our task is to assemble them into a working system.



Strategy #1: Blue-Green Deployment for C#



This is the simplest and most reliable scheme. You have two identical environments: Blue (current version) and Green (new version). You deploy the new version to Green, run smoke tests, and then instantly switch the load balancer from Blue to Green. If something goes wrong — you roll back in seconds.



How to implement this for .NET?

We'll need a load balancer (NGINX, HAProxy, or a cloud Load Balancer) and two instances of your C# service. Example NGINX configuration:



upstream backend {    server blue-server:5000 weight=100;    server green-server:5000 weight=0;  # Backup}

server { listen 80; location / { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; }}


After deploying the Green version, change the weights: blue:0, green:100. Users seamlessly flow to the new version.



Pros: simplicity, instant rollback.
Cons: requires 2x more resources (servers).



Strategy #2: Rolling Update with Kubernetes (ideal for microservices)



Kubernetes can do rolling updates "out of the box". It gradually replaces old Pods with new ones without interrupting traffic. But for this to work correctly with C#, you need to configure health probes and graceful shutdown.



Health Checks in .NET 6/8

Add an endpoint for readiness and liveness checks to your Program.cs:



using Microsoft.AspNetCore.Diagnostics.HealthChecks;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHealthChecks() .AddCheck<DatabaseHealthCheck>("database") .AddCheck<CacheHealthCheck>("redis");

var app = builder.Build();

app.MapHea

Blogs

Book Recommendations