Bird
Raised Fist0
FastAPIframework~8 mins

Startup and shutdown events in FastAPI - Performance & Optimization

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Performance: Startup and shutdown events
MEDIUM IMPACT
This concept affects the initial server readiness time and graceful shutdown, impacting how fast the app starts serving requests and releases resources.
Running heavy blocking code during startup
FastAPI
import asyncio
from fastapi import FastAPI
app = FastAPI()

@app.on_event("startup")
async def startup_event():
    await asyncio.sleep(0)  # Non-blocking placeholder
    print("App started")
Using async non-blocking code allows the server to start quickly without delay.
📈 Performance GainStartup completes immediately, improving LCP and reducing server downtime.
Running heavy blocking code during startup
FastAPI
from fastapi import FastAPI
app = FastAPI()

@app.on_event("startup")
def startup_event():
    import time
    time.sleep(5)  # Blocking delay
    print("App started")
Blocking the event loop during startup delays server readiness, increasing time before it can handle requests.
📉 Performance CostBlocks server startup for 5 seconds, delaying LCP and user interaction.
Performance Comparison
PatternBlocking BehaviorStartup DelayShutdown DelayVerdict
Blocking synchronous startup codeBlocks event loopDelays startup by secondsN/A[X] Bad
Non-blocking async startup codeNon-blockingImmediate startupN/A[OK] Good
No resource cleanup on shutdownN/AN/AProlonged shutdown, leaks[X] Bad
Async resource cleanup on shutdownNon-blockingN/AFast, clean shutdown[OK] Good
Rendering Pipeline
Startup and shutdown events run outside the browser rendering pipeline but affect server readiness and resource cleanup, indirectly impacting user experience by controlling server availability.
Server Initialization
Resource Management
⚠️ BottleneckBlocking synchronous code during startup or shutdown delays server availability.
Optimization Tips
1Avoid blocking synchronous code in startup events to reduce server readiness delay.
2Use asynchronous code for startup and shutdown handlers to keep the server responsive.
3Always clean up resources properly during shutdown to prevent leaks and slow shutdown.
Performance Quiz - 3 Questions
Test your performance knowledge
What is the main performance issue with blocking synchronous code in FastAPI startup events?
AIt delays server readiness and blocks handling requests
BIt increases CSS paint time
CIt causes layout shifts in the browser
DIt reduces JavaScript bundle size
DevTools: Network and Console panels
How to check: Use Network panel to see when server starts responding; check Console for startup logs. During shutdown, monitor server logs and resource release messages.
What to look for: Look for delays in server response after startup and any errors or warnings during shutdown indicating resource leaks.

Practice

(1/5)
1. What is the main purpose of using @app.on_event("startup") in a FastAPI application?
easy
A. To define API routes for the application.
B. To handle HTTP requests from clients.
C. To shut down the server immediately.
D. To run code when the application starts, like initializing resources.

Solution

  1. Step 1: Understand the startup event role

    The @app.on_event("startup") decorator marks a function to run when the app starts, useful for setup tasks.
  2. Step 2: Differentiate from other app parts

    Handling requests or shutting down are different concerns; startup is specifically for initialization.
  3. Final Answer:

    To run code when the application starts, like initializing resources. -> Option D
  4. Quick Check:

    Startup event = run code at app start [OK]
Hint: Startup event runs code once when app launches [OK]
Common Mistakes:
  • Confusing startup with request handling
  • Thinking startup runs multiple times per request
  • Mixing startup with shutdown event
2. Which of the following is the correct syntax to define a shutdown event handler in FastAPI?
easy
A. @app.on_event("start") def cleanup(): print("Cleaning up")
B. @app.shutdown_event def cleanup(): print("Cleaning up")
C. @app.on_event("shutdown") def cleanup(): print("Cleaning up")
D. @app.event("shutdown") def cleanup(): print("Cleaning up")

Solution

  1. Step 1: Recall correct decorator for shutdown

    The correct decorator is @app.on_event("shutdown") to run code when the app stops.
  2. Step 2: Check syntax correctness

    Options A, B, and D use incorrect decorator names or syntax.
  3. Final Answer:

    @app.on_event("shutdown")\ndef cleanup():\n print("Cleaning up") -> Option C
  4. Quick Check:

    Shutdown event decorator = @app.on_event("shutdown") [OK]
Hint: Shutdown event uses @app.on_event("shutdown") exactly [OK]
Common Mistakes:
  • Using wrong event name like "start" instead of "shutdown"
  • Missing @app.on_event decorator
  • Using non-existent decorators like @app.shutdown_event
3. Consider this FastAPI code snippet:
from fastapi import FastAPI
app = FastAPI()

@app.on_event("startup")
async def startup_event():
    print("Starting app")

@app.on_event("shutdown")
async def shutdown_event():
    print("Stopping app")

@app.get("/")
async def read_root():
    return {"message": "Hello"}

What will be printed when the server starts and then stops?
medium
A. Stopping app (on start), Starting app (on shutdown)
B. Starting app (on start), Stopping app (on shutdown)
C. Only Starting app when server starts
D. No output printed at all

Solution

  1. Step 1: Identify startup and shutdown prints

    The startup_event prints "Starting app" when the app starts, and shutdown_event prints "Stopping app" when the app stops.
  2. Step 2: Understand event timing

    These events run once each: startup at launch, shutdown at server stop.
  3. Final Answer:

    Starting app (on start), Stopping app (on shutdown) -> Option B
  4. Quick Check:

    Startup prints "Starting app", shutdown prints "Stopping app" [OK]
Hint: Startup prints on launch, shutdown prints on stop [OK]
Common Mistakes:
  • Swapping startup and shutdown outputs
  • Expecting prints on every request
  • Thinking no output occurs without explicit call
4. This FastAPI code is intended to print a message on shutdown but does not work:
from fastapi import FastAPI
app = FastAPI()

def shutdown_event():
    print("App is stopping")

app.on_event("shutdown", shutdown_event)

What is the problem?
medium
A. The decorator syntax is incorrect; should use @app.on_event("shutdown") above the function.
B. FastAPI does not support shutdown events.
C. The function name must be shutdown_handler, not shutdown_event.
D. The function must be async to work as an event handler.

Solution

  1. Step 1: Check decorator usage

    The code uses app.on_event("shutdown", shutdown_event) which incorrectly passes two arguments to on_event; it expects only the event name and returns a decorator to apply to a function.
  2. Step 2: Identify common mistake

    FastAPI expects the decorator syntax @app.on_event("shutdown") placed above the function definition for clarity and proper registration.
  3. Final Answer:

    The decorator syntax is incorrect; should use @app.on_event("shutdown") above the function. -> Option A
  4. Quick Check:

    Use @app.on_event("shutdown") decorator syntax [OK]
Hint: Always use @app.on_event("shutdown") decorator syntax [OK]
Common Mistakes:
  • Assuming function must be async (it can be sync)
  • Using wrong function names
  • Believing FastAPI lacks shutdown support
5. You want to open a database connection when your FastAPI app starts and close it when it stops. Which code correctly uses startup and shutdown events to do this?
from fastapi import FastAPI
app = FastAPI()
db = None

# Option A
@app.on_event("startup")
async def connect_db():
    global db
    db = "Connected"

@app.on_event("shutdown")
async def close_db():
    global db
    db = None

# Option B
@app.on_event("startup")
def connect_db():
    db = "Connected"

@app.on_event("shutdown")
def close_db():
    db = None

# Option C
@app.on_event("startup")
async def connect_db():
    db = "Connected"

@app.on_event("shutdown")
async def close_db():
    db = None

# Option D
@app.on_event("startup")
async def connect_db():
    global db
    db = None

@app.on_event("shutdown")
async def close_db():
    global db
    db = "Connected"
hard
A. Option A correctly manages the global db connection on startup and shutdown.
B. Option B correctly manages db without global keyword.
C. Option C correctly manages db asynchronously without global keyword.
D. Option D reverses connection and disconnection logic.

Solution

  1. Step 1: Understand global variable usage

    Since db is defined outside functions, to modify it inside functions, global db is needed.
  2. Step 2: Check startup and shutdown logic

    The correct version uses global db in both async event handlers, setting db = "Connected" on startup and db = None on shutdown. Versions without global db create local variables. One version reverses the connection and disconnection logic.
  3. Final Answer:

    Option A correctly manages the global db connection on startup and shutdown. -> Option A
  4. Quick Check:

    Use global to modify external variables in event handlers [OK]
Hint: Use global keyword to modify external variables inside event functions [OK]
Common Mistakes:
  • Forgetting global keyword causes local variable shadowing
  • Reversing startup and shutdown logic
  • Assuming async is required for all event handlers