Scenario
advanced
Race Condition in an Async Python Service
Prevent duplicate username registrations in a FastAPI service caused by a check-then-insert race condition, using database constraints and Redis locks.
The Situation
Senior Python developer / backend engineering interviews
Context: You have a FastAPI service where two concurrent requests can both check if a username is available and both register the same username, creating duplicate accounts. How do you fix this?
# BROKEN — race condition between check and insert
@app.post("/register")
async def register(username: str, db: AsyncSession = Depends(get_db)):
# Request A and B both reach here simultaneously
existing = await db.execute(select(User).where(User.username == username))
if existing.scalar():
raise HTTPException(400, "Username taken")
# Both requests pass the check above and both insert!
user = User(username=username)
db.add(user)
await db.commit() # One succeeds, one fails with IntegrityError
# FIX 1 — Database-level unique constraint + handle IntegrityError
# migrations: unique=True on username column
@app.post("/register")
async def register(username: str, db: AsyncSession = Depends(get_db)):
try:
user = User(username=username)
db.add(user)
await db.commit()
return {"id": user.id}
except IntegrityError:
await db.rollback()
raise HTTPException(400, "Username already taken")
# FIX 2 — Distributed lock with Redis (for more complex operations)
import redis.asyncio as aioredis
redis = aioredis.from_url("redis://localhost")
@app.post("/register")
async def register(username: str, db: AsyncSession = Depends(get_db)):
lock_key = f"lock:register:{username}"
async with redis.lock(lock_key, timeout=5):
existing = await db.execute(select(User).where(User.username == username))
if existing.scalar():
raise HTTPException(400, "Username taken")
user = User(username=username)
db.add(user)
await db.commit()
Best practice: Always rely on database-level constraints as the last line of defence against race conditions. Locks are for coordinating complex multi-step operations.
What You Learned
- Check-then-act race conditions
- Database-level unique constraints
- Distributed locks with Redis
Add More Questions to This Guide
Know a question that should be here? Share it and help the community!
Open Google Form