At-Least-Once vs. Exactly-Once: Understanding Message Delivery Guarantees
In distributed systems, when performing critical operations such as webhook delivery, job processing, or payment recording, a fundamental question arises:
How many times can this operation be executed?
The answer to this question determines your system's reliability and consistency guarantees.
At-Least-Once Delivery
Definition: The system guarantees that an operation will be executed at least once, with the possibility of multiple executions.
Characteristics
- Widely adopted in production systems
- Common in message queues: RabbitMQ, Kafka, Supabase Realtime
- Requires idempotent operation handlers
- Supports automatic retries on failure
- Simpler to implement and maintain
Implementation Example
// Webhook handler with idempotency export async function POST(req: Request) { const event = await req.json(); // 1. Check for duplicate processing const { data: existingEvent } = await supabase .from('webhook_logs') .select('*') .eq('event_id', event.id) .maybeSingle(); if (existingEvent) { // Event already processed, return success return new Response('Event already processed', { status: 200 }); } // 2. Record the event before processing const { error: insertError } = await supabase .from('webhook_logs') .insert({ event_id: event.id, payload: event, status: 'processing', created_at: new Date().toISOString() }); if (insertError) { return new Response('Failed to record event', { status: 500 }); } try { // 3. Process the event await processEvent(event); // 4. Update event status await supabase .from('webhook_logs') .update({ status: 'completed' }) .eq('event_id', event.id); return new Response('Event processed successfully', { status: 200 }); } catch (error) { // 5. Handle processing errors await supabase .from('webhook_logs') .update({ status: 'failed', error: error.message }) .eq('event_id', event.id); return new Response('Event processing failed', { status: 500 }); } } This implementation ensures that:
- Duplicate events are detected and handled gracefully
- Event processing is tracked and can be monitored
- Failures are properly recorded
- The system can recover from errors
Exactly-Once Delivery
Definition: The system guarantees that an operation will be executed exactly once, no more and no less.
Challenges
- Extremely difficult to implement in distributed systems
- Requires complex coordination across:
- Network layers
- State management
- Retry mechanisms
- Transaction boundaries
- Significant performance overhead
- Often unnecessary for most use cases
Even major platforms like Stripe, Kafka, and AWS don't implement exactly-once delivery by default. Instead, they rely on at-least-once delivery combined with idempotent operations.
Real-World Applications
These delivery guarantees are crucial in several scenarios:
1. Webhook Delivery
- External service notifications
- Payment processing callbacks
- Integration events
2. Background Job Processing
- Email sending
- Report generation
- Data synchronization
3. Side Effects
- Inventory updates
- Receipt generation
- Payout processing
4. Event Processing
- User notifications
- Audit logging
- System state changes
Best Practices for At-Least-Once Systems
-
Implement Idempotent Operations
- Use unique identifiers for operations
- Check for existing results before processing
- Use atomic operations where possible
-
Track Operation State
- Record operation IDs
- Track event processing status
- Maintain audit logs
-
Handle Duplicates
- Implement deduplication logic
- Use database constraints
- Maintain operation logs
-
Design for Retries
- Implement exponential backoff
- Set reasonable retry limits
- Handle partial failures
Summary
| Delivery Type | Guarantees | Implementation Complexity | Use Cases |
|---|---|---|---|
| At-Least-Once | Will execute ≥1 times | Moderate | Most production systems |
| Exactly-Once | Will execute =1 time | High | Rare, specific cases |
For most production systems, the recommended approach is:
- Implement at-least-once delivery
- Design idempotent operation handlers
- Implement proper retry mechanisms
- Maintain comprehensive logging
This combination provides the reliability and consistency needed for production systems while maintaining reasonable complexity and performance characteristics.
Top comments (0)