Concurrent requests are handled safely
Why it matters
Application-level availability checks followed by unguarded inserts are the leading cause of double bookings in production systems. Under concurrent load, two requests can both read "slot available," both pass the availability check, and both insert a booking record — all before either transaction commits. CWE-362 (race condition) and OWASP A04 (Insecure Design) both apply. A database-level UNIQUE constraint is the only mechanism that enforces the invariant atomically: the database serializes concurrent writes and rejects the duplicate at the storage layer, regardless of application concurrency.
Severity rationale
Critical because application-level checks without database constraints provably fail under concurrent load, producing confirmed double-bookings that require manual remediation and refunds.
Remediation
Add a UNIQUE constraint to your schema so the database enforces the invariant even when application-level checks race. Add this in prisma/schema.prisma (or the equivalent SQL migration).
model Booking {
id String @id @default(cuid())
slotId String
startTime DateTime
status String
@@unique([slotId, startTime]) // database-level enforcement
}
Then handle the unique constraint violation in your handler and return a structured 409 Conflict response.
Detection
-
ID:
concurrent-request-handling -
Label: Concurrent requests are handled safely
-
Severity:
critical -
What to look for: Count all database-level concurrency controls protecting booking creation: UNIQUE indexes on slot + time columns (check
schema.prisma, migration files, orCREATE TABLEstatements), serializable transaction isolation (isolation: 'Serializable',SET TRANSACTION ISOLATION LEVEL SERIALIZABLE), pessimistic locking (FOR UPDATE), or advisory locks. Also check for application-level-only patterns (find-then-insert without constraints). Enumerate: "X concurrency control mechanisms found: [list types]." -
Pass criteria: At least 1 database-level concurrency control must exist. The schema must include a UNIQUE constraint preventing overlapping bookings (e.g.,
@@unique([slotId, startTime])in Prisma,UNIQUE(slot_id, start_time)in SQL), OR transactions useSERIALIZABLEisolation level, OR row-level locking (FOR UPDATE) is used. Report:"X concurrency controls found: [UNIQUE constraint on (slotId, startTime) in schema.prisma | SERIALIZABLE isolation | FOR UPDATE locking]." -
Fail criteria: Application-level checks only (check availability then insert without db constraints or locking). This is the number 1 cause of double bookings in production. Do NOT pass when the only protection is a
findFirst/countcheck followed by acreate— without a database constraint or transaction isolation, two concurrent requests can both pass the check and both insert. -
Skip (N/A) when: Never — this is critical for any booking system.
-
Detail on fail:
"Booking creation relies on application-level 'findFirst' check followed by 'create' without database constraints or transactions. Vulnerable to race conditions under concurrent load." -
Cross-reference: The conflict-check in Booking Creation verifies the application-level availability check that this database constraint backs up.
-
Cross-reference: The transaction-atomicity check in this category verifies multi-table writes are atomic alongside this constraint.
-
Cross-reference: The pessimistic-locking check in this category covers row-level locking as an additional concurrency layer.
-
Remediation: Add a database-level UNIQUE constraint in your schema file (e.g.,
prisma/schema.prismaor migration SQL).// In schema.prisma model Booking { id String @id @default(cuid()) slotId String startTime DateTime // ... other fields @@unique([slotId, startTime]) // Prevents overlaps at DB level }
External references
- cwe · CWE-362 — Concurrent Execution Using Shared Resource with Improper Synchronization (Race Condition)
- cwe · CWE-841 — Improper Enforcement of Behavioral Workflow
- owasp:2021 · A04 — Insecure Design
- iso-25010:2011 · functional-suitability.functional-correctness
Taxons
History
- 2026-04-18·v1.0.0·Initial import from booking-flow-lifecycle·automated