System Design Fundamentals
11 items
11 items
Decoupling systems with queues, events, and async patterns
Asynchronous processing decouples producers from consumers, enabling better scalability, resilience, and user experience. Instead of waiting for slow operations (email sending, image processing, analytics), acknowledge the request immediately and process later via message queues. Key concepts include delivery guarantees (at-least-once, at-most-once, exactly-once), back pressure handling, dead letter queues for failed messages, and idempotency for safe retries. Popular systems include RabbitMQ, Kafka, SQS, and Redis Streams.
Users don't need to wait for their email to send or their image to process. Acknowledge the request immediately, queue the work, and let background workers handle it. Perceived latency drops from seconds to milliseconds.
Producers and consumers don't need to be online simultaneously. The producer writes to the queue and moves on. The consumer processes when ready. This handles traffic spikes without overloading downstream systems.
At-least-once delivery with idempotent consumers is the safest pattern. Messages may be delivered multiple times on failures, but idempotent processing ensures the same result regardless of retry count.
Synchronous: Caller waits for response. Simple but couples caller to callee.
Asynchronous: Caller sends request and continues. Response delivered later via callback, polling, or websocket.
When to use async: - Operation is slow (email, SMS, image processing) - Downstream system is unreliable - Result isn't needed immediately - Want to smooth traffic spikes
Benefits of async: - Better user experience (fast response) - Resilience (retry failed operations) - Scalability (buffer traffic spikes) - Decoupling (services evolve independently)