When the beta image runs with --workers > 1 (default: 2), every worker calls lifespan() in parallel. Each worker sees an empty DB, then seed_if_empty() runs concurrently, producing 2x (or Nx) demo entries. Fix: wrap the seed operation in a process-wide FileLock. Even if a worker loses the race it re-checks the table count inside the critical section and returns without re-seeding. Verified by cold-starting a 4-worker container: 8 items (was: 32).