No-downtime deployments: Changing the signature of a background task

Adrienne Domingus
3 min readMar 17, 2018

No-downtime deployments is one of my favorite things to think about. It requires thinking about inputs and outputs and the different states of your application and database and other infrastructure during the phases of a deployment. It requires you to be intentional about how you make changes, not just what changes you make.

As business needs change and features evolve, it is common to change the signature of a function. Usually this is fine — you can control what the input of a function is, and adjust the logic within the function accordingly. Not so simple when your function is a background task though!

The Problem

The problem here is best demonstrated by example. Lets say you have a task that currently looks like this (Syntax in the examples assumes you’re using celery with Django, but the concepts apply even if you’re not!):


and you now need it to take an additional parameter, so that it looks like this:

def do_something
(arg_1, arg_2):

The issue here is that background tasks are definitionally not evaluated at the time they are enqueued, so a task that was enqueued with only arg_1 passed in will throw an error if you’ve deployed your change between when it was enqueued and when it will be processed — by the time it’s picked up, the function is expecting both arg_1 and arg_2 to be passed in, and it only has arg_1!

This is most likely only a problem for a minute or two, while your app finishes processing any tasks that were enqueued before the change, and it will then self-resolve, but some number of tasks will not be able to be processed successfully. This is obviously not ideal.

The Solution

As is often the case with challenges like these, a change like this will need to be made in phases, and doing it without downtime will require multiple deployments. We’ll take advantage of the fact that this works in Python:

This means that we can do the following:

  1. Deploy a change that: