📖 Scenario: You are building a simple FastAPI application that needs to manage a database connection properly. You want to open the connection when the app starts and close it when the app shuts down.
🎯 Goal: Create a FastAPI app that opens a connection on startup and closes it on shutdown using event handlers.
📋 What You'll Learn
Create a FastAPI app instance named app
Define a variable db_connection initialized to None
Add a startup event handler function named connect_to_db that sets db_connection to the string 'Database Connected'
Add a shutdown event handler function named close_db_connection that sets db_connection to None
Register the startup and shutdown event handlers with the app instance
💡 Why This Matters
🌍 Real World
Managing database or external service connections properly is essential in web applications to avoid resource leaks and ensure smooth operation.
💼 Career
Understanding connection lifecycle management is important for backend developers working with FastAPI or similar frameworks to build reliable and maintainable APIs.
Progress0 / 4 steps
1
Create FastAPI app and initialize connection variable
Create a FastAPI app instance called app and create a variable called db_connection set to None.
FastAPI
Hint
Use app = FastAPI() to create the app and db_connection = None to initialize the connection variable.
2
Define startup event handler to open connection
Define a function called connect_to_db decorated with @app.on_event('startup') that sets db_connection to the string 'Database Connected'.
FastAPI
Hint
Use @app.on_event('startup') to decorate the function and assign the string to db_connection inside the function.
3
Define shutdown event handler to close connection
Define a function called close_db_connection decorated with @app.on_event('shutdown') that sets db_connection to None.
FastAPI
Hint
Use @app.on_event('shutdown') to decorate the function and set db_connection to None inside it.
4
Add a simple root path to verify app runs
Add a path operation function called read_root decorated with @app.get('/') that returns a dictionary with the key 'status' and the value of db_connection.
FastAPI
Hint
Use @app.get('/') to decorate the function and return a dictionary with the current db_connection value.
Practice
(1/5)
1. What is the main purpose of using yield in FastAPI dependencies for connection lifecycle management?
easy
A. To setup a resource before the request and clean it up after the request
B. To define a synchronous function only
C. To permanently keep a connection open for all requests
D. To return multiple values from a function
Solution
Step 1: Understand yield in dependencies
In FastAPI, yield is used in dependencies to create a setup before the request and a cleanup after the request finishes.
Step 2: Identify the lifecycle role
This pattern ensures resources like database connections open before and close after each request, preventing leaks.
Final Answer:
To setup a resource before the request and clean it up after the request -> Option A
Quick Check:
Yield in dependencies = setup and cleanup per request [OK]
Hint: Yield in dependencies means setup before and cleanup after request [OK]
Common Mistakes:
Thinking yield returns multiple values at once
Assuming yield keeps connection open forever
Confusing yield with async context managers
2. Which of the following is the correct way to define a FastAPI dependency that opens a connection before a request and closes it after using yield?
easy
A. def get_conn():
conn = open_conn()
yield conn
return
conn.close()
B. def get_conn():
conn = open_conn()
return conn
conn.close()
C. async def get_conn():
conn = open_conn()
yield conn
conn.close()
D. def get_conn():
conn = open_conn()
yield conn
conn.close()
Solution
Step 1: Check the use of yield for setup and cleanup
def get_conn():
conn = open_conn()
yield conn
conn.close() correctly uses yield to provide the connection and then closes it after the request.
Step 2: Identify syntax and flow correctness
def get_conn():
conn = open_conn()
return conn
conn.close() returns before closing, so cleanup never runs. async def get_conn():
conn = open_conn()
yield conn
conn.close() mixes async with a sync open_conn (may cause issues). def get_conn():
conn = open_conn()
yield conn
return
conn.close() returns early after yield, skipping cleanup.
A. Missing async keyword before function definition
B. Cannot combine @app.on_event with @asynccontextmanager on the same function
C. Yield cannot be used in async functions
D. No error, this is correct usage
Solution
Step 1: Understand decorator usage for startup events
The @app.on_event("startup") expects a normal async function, not an async context manager.
Step 2: Recognize conflict of decorators
Using @asynccontextmanager with @app.on_event on the same function is invalid because FastAPI expects a coroutine, not a context manager.
Final Answer:
Cannot combine @app.on_event with @asynccontextmanager on the same function -> Option B
Quick Check:
@app.on_event and @asynccontextmanager cannot be combined [OK]
Hint: Don't mix @app.on_event with @asynccontextmanager on one function [OK]
Common Mistakes:
Assuming yield is invalid in async functions
Forgetting async keyword
Thinking this pattern is valid
5. You want to manage a database connection pool that opens once when the FastAPI app starts and closes when it shuts down. Which is the best way to implement this lifecycle management?
hard
A. Use @app.on_event("startup") to open and @app.on_event("shutdown") to close the pool directly without context managers
B. Use a dependency with yield to open and close the pool per request
C. Open the pool globally outside FastAPI and never close it
D. Use @asynccontextmanager to create a context manager function and call it in @app.on_event("startup") and @app.on_event("shutdown")
Solution
Step 1: Understand app-wide resource lifecycle
A connection pool should open once at app startup and close at shutdown, not per request.
Step 2: Choose correct FastAPI pattern
Using @app.on_event("startup") and @app.on_event("shutdown") to open and close the pool directly is the simplest and recommended way.
Step 3: Why not others?
Use @asynccontextmanager to create a context manager function and call it in @app.on_event("startup") and @app.on_event("shutdown") misuses @asynccontextmanager with events. Use a dependency with yield to open and close the pool per request opens/closes per request, which is inefficient. Open the pool globally outside FastAPI and never close it never closes, risking resource leaks.
Final Answer:
Use @app.on_event("startup") to open and @app.on_event("shutdown") to close the pool directly without context managers -> Option A
Quick Check:
App startup/shutdown events manage global resources best [OK]
Hint: Use startup and shutdown events for global resource management [OK]
Common Mistakes:
Opening/closing pool per request wastes resources
Not closing pool causes leaks
Misusing asynccontextmanager for app events
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.