ā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:
- Built in concurrency support
- Auto-generated interactive documentation for the routes in your appĀ
- Performance is a feature; according to independent benchmarks, FastAPI lives up to its name.
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
- A LaunchDarkly account - sign up for free here
- A local developer environment with git, Python and pip installed
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:
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.
Configure the flag as follows:
- Name: raccoon_facts_api
- Description: Upgrade the raccoon facts API from V0 to V1.
- Configuration: release
- Flag type: Number
- Variations:
- API version 0: 0
- API version 1: 1
- When targeting is OFF, serve version 0
- When targeting is ON, serve version 1
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.ā
The progressive rollout dialog has some sensible defaults. If I was rolling out a production API, Iād probably keep these as is.
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.ā
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
When everything looks good to go, click the āConfirmā button.Ā
On the next screen click āReview and save.ā
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.ā
The next screen will show the progress of your 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. š
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.