| name | concurrency-security |
| description | TOCTOU prevention, distributed locking, idempotency keys, race condition detection for Node.js and serverless environments. |
Concurrency Security
Patterns for preventing race conditions, double-execution, and state corruption in concurrent systems.
TOCTOU Prevention
Time-of-Check to Time-of-Use: the gap between reading state and acting on it.
const balance = await db.accounts.findUnique({ where: { id } })
if (balance.amount >= amount) {
await db.accounts.update({ where: { id }, data: { amount: balance.amount - amount } })
}
const updated = await db.$executeRaw`
UPDATE accounts
SET amount = amount - ${amount}
WHERE id = ${id} AND amount >= ${amount}
RETURNING *
`
if (updated.count === 0) throw new Error('Insufficient funds or concurrent update')
if (fs.existsSync(filePath)) {
fs.writeFileSync(filePath, data)
}
import { open } from 'fs/promises'
try {
const fh = await open(filePath, 'wx')
await fh.writeFile(data)
await fh.close()
} catch (err: any) {
if (err.code === 'EEXIST') { }
throw err
}
Distributed Locking with Redis
import Redis from 'ioredis'
const redis = new Redis(process.env.REDIS_URL!)
async function acquireLock(key: string, ttlMs: number): Promise<string | null> {
const token = crypto.randomUUID()
const result = await redis.set(`lock:${key}`, token, 'NX', 'PX', ttlMs)
return result === 'OK' ? token : null
}
async function releaseLock(key: string, token: string): Promise<void> {
const script = `
if redis.call("GET", KEYS[1]) == ARGV[1] then
return redis.call("DEL", KEYS[1])
else
return 0
end
`
await redis.eval(script, 1, `lock:`, token)
}
() {
token = (paymentId, )
(!token) ()
{
(paymentId)
} {
(paymentId, token)
}
}
Redlock Algorithm (multi-node)
import Redlock from 'redlock'
import Redis from 'ioredis'
const clients = [
new Redis('redis://redis1:6379'),
new Redis('redis://redis2:6379'),
new Redis('redis://redis3:6379'),
]
const redlock = new Redlock(clients, {
retryCount: 3,
retryDelay: 200,
retryJitter: 100,
})
async function criticalSection(resourceId: string) {
await redlock.using([`resource:${resourceId}`], 10_000, async (signal) => {
if (signal.aborted) throw signal.error
await performAtomicOperation(resourceId)
if (signal.aborted) throw signal.error
})
}
PostgreSQL Advisory Locks
import { Pool } from 'pg'
const pool = new Pool()
async function withAdvisoryLock<T>(lockId: number, fn: () => Promise<T>): Promise<T> {
const client = await pool.connect()
try {
await client.query('SELECT pg_advisory_lock($1)', [lockId])
return await fn()
} finally {
await client.query('SELECT pg_advisory_unlock($1)', [lockId])
client.release()
}
}
async function tryAdvisoryLock(lockId: number): Promise<boolean> {
const client = await pool.connect()
try {
const { rows } = await client.query('SELECT pg_try_advisory_lock($1) AS acquired', [lockId])
return rows[].
} {
client.()
}
}
=
(, () => {
()
})
Idempotency Key Implementation
import { Request, Response, NextFunction } from 'express'
import { db } from './db'
export async function idempotencyMiddleware(req: Request, res: Response, next: NextFunction) {
const idempotencyKey = req.headers['idempotency-key'] as string | undefined
if (!idempotencyKey || req.method === 'GET') return next()
const existing = await db.idempotencyKeys.findUnique({
where: { key: idempotencyKey },
})
if (existing) {
return res.status(existing.statusCode).json(existing.responseBody)
}
const originalJson = res.json.bind(res)
res. = {
db..({
: {
: idempotencyKey,
: res.,
: body,
: (.() + * * * ),
},
}).(.)
(body)
}
()
}
CREATE TABLE idempotency_keys (
key TEXT PRIMARY KEY,
status_code INT NOT NULL,
response_body JSONB NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(),
expires_at TIMESTAMPTZ NOT NULL
);
CREATE INDEX ON idempotency_keys (expires_at);
Atomic Database Operations
async function debitAccount(accountId: string, amount: number) {
await db.$transaction(async (tx) => {
const account = await tx.$queryRaw<Account[]>`
SELECT * FROM accounts WHERE id = ${accountId} FOR UPDATE
`
if (!account[0] || account[0].balance < amount) {
throw new Error('Insufficient funds')
}
await tx.$executeRaw`
UPDATE accounts SET balance = balance - ${amount} WHERE id = ${accountId}
`
})
}
await db.$executeRaw`
INSERT INTO user_stats (user_id, login_count, last_login)
VALUES (${userId}, 1, NOW())
ON CONFLICT (user_id)
DO UPDATE SET
login_count = user_stats.login_count + 1,
last_login = NOW()
`
Double-Submit Prevention
async function submitForm(data: FormData) {
const key = crypto.randomUUID()
const response = await fetch('/api/checkout', {
method: 'POST',
headers: { 'Idempotency-Key': key },
body: JSON.stringify(data),
})
return response.json()
}
async function handleStripeWebhook(req: Request, res: Response) {
const event = stripe.webhooks.constructEvent(
req.body, req.headers['stripe-signature']!, process.env.STRIPE_WEBHOOK_SECRET!
)
try {
await db.$executeRaw`
INSERT INTO processed_webhook_events (event_id, processed_at)
VALUES (${event.id}, NOW())
`
} catch (: ) {
(err. === ) {
res.().({ : })
}
err
}
(event)
res.().({ : })
}
Optimistic vs Pessimistic Concurrency Control
interface Document {
id: string
content: string
version: number
}
async function updateDocument(id: string, content: string, expectedVersion: number) {
const result = await db.$executeRaw`
UPDATE documents
SET content = ${content}, version = version + 1
WHERE id = ${id} AND version = ${expectedVersion}
`
if (result === 0) throw new Error('Conflict: document was modified by another process')
}
async function updateDocumentPessimistic(id: string, content: string) {
await db.$transaction(async (tx) => {
await tx.$queryRaw`SELECT 1 FROM documents WHERE id = ${id} FOR UPDATE`
await tx.$executeRaw
})
}
Serverless Cold Start Race Conditions
import { DynamoDB } from '@aws-sdk/client-dynamodb'
const ddb = new DynamoDB({})
async function initializeOnce(jobId: string): Promise<boolean> {
try {
await ddb.putItem({
TableName: 'distributed-locks',
Item: { pk: { S: `init:${jobId}` } },
ConditionExpression: 'attribute_not_exists(pk)',
})
return true
} catch (err: any) {
if (err.name === 'ConditionalCheckFailedException') return false
throw err
}
}
Testing for Race Conditions
async function testConcurrentDebit() {
const accountId = await createTestAccount({ balance: 100 })
const debitAmount = 100
const results = await Promise.allSettled(
Array.from({ length: 10 }, () => debitAccount(accountId, debitAmount))
)
const successes = results.filter(r => r.status === 'fulfilled')
const failures = results.filter(r => r.status === 'rejected')
console.assert(successes.length === 1, `Expected 1 success, got ${successes.length}`)
console.assert(failures.length === 9, `Expected 9 failures, got ${failures.length}`)
const account = await (accountId)
.(account. === , )
}
Core rule: Every shared mutable resource needs either an atomic operation, a lock, or an idempotency guard. "It works in testing" is not enough — test with parallel load.