Upgrade your APIs safely with Progressive Rollouts in a Python FastAPI Application featured image

ā€œI love tailing the logs and refreshing my release dashboard!ā€ said no developer ever.

Releases are a prime area where bad ships can happen. Progressive rollouts allow you to release features to your users, a little bit at a time, at a pace you control. Good news - progressive rollouts are now generally available in LaunchDarklyā€™s free plan!Ā 


In this tutorial you will learn how to use progressive rollouts in your Python FastAPI application to upgrade to a new API version. Three raccoons in a trench coat ā€“ I mean our team of backend developers ā€“ have been hard at work coding a new version of the raccoon facts API. Weā€™d hate to break our beloved Raccoon Facts website, so letā€™s roll out the new API progressively so we can monitor for any regressions that might come up.

What is FastAPI?

FastAPI is a new kid on the block in terms of Python frameworks. It offers many benefits such as:

The example API used in this project was also built with FastAPI, in about 5 minutes, and deployed to a free Render account equally quickly. Crowdsourcing the facts from X/Twitter and Mastodon took longer than writing the code and deployhing to prod. Huge thanks to everyone who contributed!

Prerequisites

Get started with the example FastAPI LaunchDarkly app

Weā€™ve written an example app that shows you a raccoon fact. It has a routing layer and a minimalist front end, since the raccoons couldnā€™t afford any designers.Ā 

Weā€™ll add some logic to the routing layer to choose which version of the API to use, based on a LaunchDarkly flag value. Then weā€™ll use the progressive rollout workflow to gradually switch over to the new version of the API.

Clone the example repository:

git clone https://github.com/annthurium/fastapi-raccoon-facts 

Set up and activate your virtual environment:

python -m venv venv
source venv/bin/activate

Install dependencies:

pip install -r requirements.txt

Run the server by typing the following command in your terminal:

fastapi dev main.py

If you open http://127.0.0.1:8000/ in a browser, you should see a page with a raccoon fact and the API version. šŸ¦

Gating API updates with a LaunchDarkly flag in a FastAPI applicationĀ 

Log in to your LaunchDarkly account. Copy your SDK key from the environment dropdown menu:

copy your SDK key from the LaunchDarkly app.

Paste the sdk key into the .env.example file in the repository. Save the file renamed as ā€œ.envā€

Run the following command in your terminal:

source .env

In your editor, open main.py. Add the following commented lines of code:

from fastapi import FastAPI

from fastapi.responses import HTMLResponse
import requests

# Add the following new import statements
from contextlib import asynccontextmanager
import ldclient
from ldclient import Context
from ldclient.config import Config
import os

# Add this new function to instantiate and shut down the LaunchDarkly client
@asynccontextmanager
async def lifespan(app: FastAPI):
  # initialize the LaunchDarkly SDK
  ld_sdk_key = os.getenv("LAUNCHDARKLY_SDK_KEY")
  ldclient.set_config(Config(ld_sdk_key))
  yield
  # Shut down the connection to the LaunchDarkly client
  ldclient.get().close()

# Add the new lifespan parameter
app = FastAPI(lifespan=lifespan)

async def get_raccoon_fact(api_version):
   url = f"https://versioned-api.onrender.com/v{api_version}/fact/"
   headers = {"Accept": "application/json", "User-Agent": "LaunchDarkly Progressive Rollout Tutorial"}
   response = requests.get(url=url, headers=headers)
   return response.json()

@app.get("/", response_class=HTMLResponse)
async def read_root():
   # add and change the following lines of code to evaluate the flag
   context = Context.builder("context-key-123abc").name("Raccacoonie").build()
   api_version = ldclient.get().variation("raccoon_api_version", context, "0")
   print("API VERSION!!!!", api_version)
   fact = await get_raccoon_fact(api_version=api_version)

   html = """
   <html>
       <head>
           <title>Raccoon facts!</title>
       </head>
       <body>
           <h1>Wacky raccoon facts!!!</h1>
           <h2>{fact}</h2>
           <p>api version: {api_version}</p>
       </body>
   </html>
   """.format(fact=fact, api_version=api_version)
   return html

If you reload http://127.0.0.1:8000/ in your browser, you should still see a fact from Version 1 of the API.

Set up your progressive rollout

Head over to the LaunchDarkly app.Ā 

Create a flag by clicking either of the ā€œCreate flagā€ buttons.

empty state of the LaunchDarkly app showing two "Create flag" buttons.

Configure the flag as follows:

  • Name: raccoon_facts_api
  • Description: Upgrade the raccoon facts API from V0 to V1.
  • Configuration: release
  • Flag type: Number

Creating a flag for a progressive rollout - first configuration step.

  • Variations:
  • API version 0: 0
  • API version 1: 1
  • When targeting is OFF, serve version 0
  • When targeting is ON, serve version 1

Flag configuration for progressive rollout.

Click ā€œCreate flag.ā€

Adding a progressive rollout to a LaunchDarkly flag

On the next screen, click the ā€œAdd rolloutā€ button next to ā€œDefault ruleā€ and select ā€œProgressive rollout.ā€

Create a progressive rollout dropdown.

The progressive rollout dialog has some sensible defaults. If I was rolling out a production API, Iā€™d probably keep these as is.

Default timeline for progressive rollouts.

The backend raccoons ainā€™t got time for that, and I bet you donā€™t either. Iā€™ll remove some steps so you can see what a completed rollout looks like in just two minutes.Ā 

Delete unwanted rollout stages by clicking on the ā€œ...ā€ button, and selecting ā€œDelete.ā€

How to delete unwanted progressive rollout stages.

Your finished configuration should be the following:

  • Turn flag on: On
  • Variation to roll out: v1
  • Context kind to roll out by: user
  • Roll out to 25% for 1 minute
  • Roll out to 50% for 1 minute

demo timeline for progressive rollouts in 2 minutes or your pizza is free.

When everything looks good to go, click the ā€œConfirmā€ button.Ā 

On the next screen click ā€œReview and save.ā€

How to review and save your progressive rollout.

If your settings require confirming changes, add a comment here: ā€œRolling out v1 of raccoon facts api. Trash bandits, assemble!ā€ Type the name of the environment to confirm. Click ā€œSave changes.ā€

Confirmation screen for changing flag configuration.

The next screen will show the progress of your rollout:

UI displaying the progress of your progressive rollout.

Take a 2 minute break. Go get a coffee, or rummage through some trash. Iā€™m not here to judge.

After that time has passed, reload http://localhost:8000/. You should see new, wackier facts from the v1 version of the API. The Progressive Rollout UI will also update to indicate that version 1 is being served to 100% of users. šŸŽ‰

UI showing that the new version of the API is being served to 100% of users.

In this post youā€™ve learned to use LaunchDarklyā€™s progressive rollouts to migrate to a newer version of an API, automatically, at a pace thatā€™s most comfortable to you. Progressive rollouts can be used for your regularly scheduled releases as well as riskier launches.Ā 

If you want to show off what youā€™ve built, or just share your most outlandish raccoon fact, holler at me via email (tthurium@launchdarkly.com), X/Twitter, Mastodon, Discord or LinkedIn.

Like what you read?
Get a demo
Related Content

More about De-risked releases

October 2, 2024