Async and Real-time Features

Back

Loading concept...

FastAPI: Async & Real-time Features ๐Ÿš€

The Restaurant That Never Sleeps

Imagine you run a very busy restaurant. You have ONE waiter. Every time a customer orders food, should the waiter stand at the kitchen door waiting for the chef to finish cooking? Or should the waiter take orders from other tables while the food is being prepared?

Thatโ€™s exactly what async programming is about!

In FastAPI, async means your server can handle multiple requests at the same time, without getting stuck waiting.


๐ŸŽญ Part 1: Async Path Operations

What is an Async Path Operation?

Think of a path operation as a door to your restaurant. When someone knocks (makes a request), you answer.

Regular (Sync) Door:

@app.get("/food")
def get_food():
    # Waiter stands and waits
    food = cook_slowly()
    return food

Async Door:

@app.get("/food")
async def get_food():
    # Waiter goes to help others
    food = await cook_slowly()
    return food

The Magic Word: await

When you see await, think of it as telling the waiter:

โ€œGo help other customers. Come back when this is ready!โ€

from fastapi import FastAPI

app = FastAPI()

@app.get("/weather")
async def get_weather():
    # Go do other things while waiting
    data = await fetch_weather_api()
    return {"weather": data}

When to Use async?

graph TD A["Does your code wait for something?"] --> B{What kind?} B --> C["Database query"] B --> D["External API call"] B --> E["File reading"] C --> F["Use async + await"] D --> F E --> F A --> G["Just calculations?"] G --> H["Regular def is fine"]

Simple Example: Two Customers

Without async:

  • Customer A orders โ†’ waits 5 seconds โ†’ served
  • Customer B orders โ†’ waits 5 seconds โ†’ served
  • Total time: 10 seconds

With async:

  • Customer A orders โ†’ cooking starts
  • Customer B orders โ†’ cooking starts
  • Both served around the same time!
  • Total time: ~5 seconds
import asyncio
from fastapi import FastAPI

app = FastAPI()

@app.get("/order/{item}")
async def place_order(item: str):
    # This simulates cooking time
    await asyncio.sleep(3)
    return {"order": item, "status": "ready!"}

๐ŸŽ’ Part 2: Background Tasks

The Busy Bee Helper

Sometimes you want to tell the customer โ€œYour order is placed!โ€ immediately, but then do extra work in the background.

Real example: When you sign up for a website, it says โ€œWelcome!โ€ right away. But the email confirmation is sent in the background.

How Background Tasks Work

from fastapi import BackgroundTasks

@app.post("/signup")
async def signup(
    email: str,
    background_tasks: BackgroundTasks
):
    # This happens AFTER the response
    background_tasks.add_task(
        send_welcome_email,
        email
    )
    # Customer sees this immediately!
    return {"message": "Welcome!"}

def send_welcome_email(email: str):
    # This runs in background
    print(f"Sending email to {email}")

The Kitchen Ticket System

graph TD A["Customer Orders"] --> B["Waiter says: Coming right up!"] B --> C["Response sent immediately"] B --> D["Kitchen gets ticket"] D --> E["Background: Prepare food"] E --> F["Background: Pack order"]

Multiple Background Tasks

You can add many tasks! They run one after another.

@app.post("/order")
async def create_order(
    order_id: str,
    background_tasks: BackgroundTasks
):
    # Add multiple background jobs
    background_tasks.add_task(
        save_to_database,
        order_id
    )
    background_tasks.add_task(
        notify_kitchen,
        order_id
    )
    background_tasks.add_task(
        send_receipt,
        order_id
    )

    return {"order_id": order_id}

When to Use Background Tasks?

โœ… Good For โŒ Not Good For
Sending emails Critical database saves
Logging events Payment processing
Cleanup jobs User authentication
Notifications Data that user needs NOW

๐Ÿ”Œ Part 3: WebSocket Endpoints

The Two-Way Walkie-Talkie

Regular HTTP is like sending letters:

  • You send a letter โ†’ Wait โ†’ Get a reply
  • For every question, you send a new letter

WebSocket is like a phone call:

  • You connect once
  • Both sides can talk anytime
  • No need to reconnect!

Why WebSockets Matter

graph LR subgraph Regular HTTP A["Client"] -->|Request 1| B["Server"] B -->|Response 1| A A -->|Request 2| B B -->|Response 2| A end
graph LR subgraph WebSocket C["Client"] <-->|Always connected| D["Server"] end

Your First WebSocket

from fastapi import WebSocket

@app.websocket("/chat")
async def chat(websocket: WebSocket):
    # Step 1: Accept the connection
    await websocket.accept()

    while True:
        # Step 2: Wait for message
        message = await websocket.receive_text()

        # Step 3: Send response
        await websocket.send_text(
            f"You said: {message}"
        )

The Chat Room Example

Think of it like this:

  1. ๐Ÿ“ฑ Phone rings (client connects)
  2. ๐Ÿ“ž You pick up (accept connection)
  3. ๐Ÿ—ฃ๏ธ They talk (receive message)
  4. ๐Ÿ’ฌ You reply (send message)
  5. ๐Ÿ” Keep talking (loop continues)
  6. ๐Ÿ“ด Hang up (connection closes)

Handling Multiple Users

# Keep track of all connected users
connected_users = []

@app.websocket("/chat-room")
async def chat_room(websocket: WebSocket):
    await websocket.accept()
    connected_users.append(websocket)

    try:
        while True:
            message = await websocket.receive_text()
            # Send to ALL users
            for user in connected_users:
                await user.send_text(message)
    except:
        connected_users.remove(websocket)

WebSocket Message Types

# Text messages (like chat)
text = await websocket.receive_text()
await websocket.send_text("Hello!")

# JSON data (structured info)
data = await websocket.receive_json()
await websocket.send_json({"status": "ok"})

# Binary (files, images)
bytes_data = await websocket.receive_bytes()
await websocket.send_bytes(image_data)

๐ŸŽฏ Putting It All Together

Real-World Scenario: Live Game Score

from fastapi import FastAPI, WebSocket
from fastapi import BackgroundTasks

app = FastAPI()
game_subscribers = []

# WebSocket: Live updates
@app.websocket("/live-score")
async def live_score(websocket: WebSocket):
    await websocket.accept()
    game_subscribers.append(websocket)

    try:
        while True:
            await websocket.receive_text()
    except:
        game_subscribers.remove(websocket)

# Async endpoint: Update score
@app.post("/update-score")
async def update_score(
    team: str,
    score: int,
    background_tasks: BackgroundTasks
):
    # Background: Notify all watchers
    background_tasks.add_task(
        broadcast_score,
        team,
        score
    )
    return {"updated": True}

async def broadcast_score(team, score):
    for subscriber in game_subscribers:
        await subscriber.send_json({
            "team": team,
            "score": score
        })

๐ŸŒŸ Remember This!

Feature Think Of It As Use When
async/await Multi-tasking waiter Waiting for slow things
Background Tasks Kitchen ticket system Work after responding
WebSocket Phone call Real-time updates

The Golden Rules

  1. async = โ€œI can do other things while waitingโ€
  2. await = โ€œStart this, come back when doneโ€
  3. BackgroundTasks = โ€œDo this later, reply nowโ€
  4. WebSocket = โ€œStay connected, talk anytimeโ€

๐ŸŽ‰ You Did It!

You now understand FastAPIโ€™s real-time superpowers:

โœ… Async Path Operations - Handle many requests without blocking โœ… Background Tasks - Do work after responding โœ… WebSockets - Real-time two-way communication

Your FastAPI apps can now be fast, responsive, and real-time! ๐Ÿš€

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.