Architecture and Processing

Webhook Concurrency and Race Conditions

Webhook events often arrive in bursts. When multiple events modify the same resource at the same time, race conditions can corrupt data or cause incorrect state transitions.

Example race condition

Imagine a payment provider sending two events:

  • invoice.paid
  • subscription.updated

If both webhooks update the same database record simultaneously, one write may overwrite the other.

Why concurrency happens

Most webhook providers deliver events asynchronously and in parallel.

Large systems frequently send multiple events for a single action. This makes concurrency unavoidable.

Queue webhook processing

The first rule of production webhook handling is:

never process heavy logic inside the HTTP request.

                    dispatch(new ProcessWebhookEvent($payload));
                

Queues isolate webhook ingestion from business logic execution.

Database locking

When multiple events update the same resource, use database locks.

                    
DB::transaction(function () use ($userId) {

    $user = User::lockForUpdate()->find($userId);

    $user->subscription_status = 'active';

    $user->save();

});
                    
                

This prevents concurrent updates from corrupting the record.

Optimistic concurrency

Another strategy is optimistic locking using version numbers.

                    
update users
set version = version + 1
where id = ? and version = ?
                    
                

If the version changes, the update fails and the job retries.

Idempotent webhook handlers

Idempotency is essential for concurrency safety.

Each webhook event should be processed only once.

                    
WebhookEvent::firstOrCreate([
    'event_id' => $eventId
]);
                    
                

If the event was already processed, the handler simply exits.

Observing concurrency problems

Race conditions are difficult to detect because failures happen under load. Monitoring webhook execution timelines helps identify overlapping events.

A monitoring tool can show exactly when multiple events were delivered and how long each handler took to execute.

Related guides:

Start monitoring your webhook endpoints →