# Overview A message queue is a system component used to hold messages (i.e., data) between components of the system. It allows for upstream components to send off their results and move onto processing new information without waiting for a downstream component to become available. Additionally, it allows the downstream component to have a single point to check for work. Moreover, the downstream component can also scale based on the size of this queue. The ability to use a message queue to remove the dependency between the upstream and downstream system components is referred to as 'decoupling'. \ ## General Use Cases Message queues can be a key system component for the following use cases: - Handling Bursty Traffic - Distributing Work Across a System # Key Considerations A message queue may not be a good fit for systems with [[Synchronous]] workloads. Also, if there is a low [[latency]] (e.g., 500ms), the introduction of a queue may slow down processing. ## Delivery Semantics | Approach | Description | Pros | Cons | Use Cases | | -------------------------- | ----------- | ---- | ---- | --------- | | [[At Least Once Delivery]] | | | | | | [[At Most Once Delivery]] | | | | | | [[Exactly Once Delivery]] | | | | | | | | | | | ## Retention ## Message Ordering A message queue can be configured to handle incoming and outgoing messages in various manners. The most common approaches for managing message ordering are: | Approach | Description | Pros | Cons | Use Cases | | ----------------- | ----------- | ---- | ---- | --------- | | [[FIFO - Queues]] | | | | | | [[LIFO - Queues]] | | | | | ## Retention - Time-based - Least Recently Used (LRU) ## Scaling ### Partitioning Similar to databases, a message queue can be partitioned across multiple servers to handle more messages. This will require a [[Partitioning]] strategy that ensures related messages are stored on the same partition. ### Backpressure [[Backpressure]] is an approach to use if a message queue is having trouble keeping up with demand. This approach slows down the production of new message queues by rejecting new messages (or slowing down the rate which new message are accepted) by sending an error to a user or producer. ## [[Exception Handling]] Since messages are persistent in a message queue, there is an opportunity to retry processing of a message in the case of an issue. There are various retry mechanisms that can be considered: ![[Exception Handling#Retry (failure) Mechanisms]] If a message is deemed to be un-processable it can be placed in a 'special' type of message queue called a [[Dead Letter Queue (DLQ)]]. This is a message queue whose sole purpose to hold messages that cannot be processed (i.e., a dead letter). # Implementation Details ## Design Patterns | Pattern | Description | Pros | Cons | Use Cases | | ------------------- | ----------- | ---- | ---- | --------- | | [[Fanout-on-read]] | | | | | | [[Fanout-on-write]] | | | | | | | | | | | ## Scaling and Performance ![[Back of the Envelope Estimation#Message Queues]] # Useful Links ## Products - [[Redis]] - [[AWS SQS]] - [[RabbitMQ]] - [[Kafka]] # Related Topics ## Reference #### Working Notes #### Sources --- Topics to discuss when you use a message queue in a system design interview... #flashcard - Delivery Semantics (atleast once, at most once, exactly once) - Partitioning - Message ordering (FIFO, LIFO, etc.) - Retry (failures) - Retention ---