October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk4 min

Elixir Backpressure: Key Ways to Manage Message Flow

When Elixir producers outpace consumers, messages can pile up. Compare stop-and-wait and demand windows, and decide how to handle overload when an upstream source cannot slow down.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When an Elixir producer sends messages faster than a consumer can process them, the consumer’s mailbox can grow into a backlog. The solution is to make flow control explicit: wait for acknowledgements, let consumers request bounded demand, or choose a deliberate overload policy when the upstream source cannot be slowed.

One illustrative scenario is a publisher emitting 10,000 messages per second while an email notifier can send 50 per second. Those figures frame the problem; they are not industry measurements. The important question is what happens to work the consumer cannot yet handle.

As an Amazon Associate I earn from qualifying purchases.

Why asynchronous messaging can create a backlog

In the example discussed by krishnadaspc in Part 9 of Building Distributed Systems in Elixir, send/2 is asynchronous from the sender’s perspective: sending a message does not mean the recipient has finished processing it. If messages arrive faster than the recipient handles them, queued work accumulates.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

This is not necessarily a problem for every short burst. It becomes a capacity problem when the producer remains faster over time, or when a burst creates more queued work than the process can safely retain. A growing mailbox can increase memory use and delay useful work behind older messages.

Three ways to control the flow

Approach How flow is controlled Backlog and trade-off When it fits
Uncoordinated push The producer sends without waiting for consumer progress. No acknowledgement round trip, but a slow consumer can accumulate queued messages. Fire-and-forget work only when backlog and loss risks are handled elsewhere.
Stop-and-wait The producer sends one item and waits for an acknowledgement associated with that item’s reference. In the simple pattern, roughly one item is outstanding at a time. Work is serialized, and each acknowledgement’s latency affects progress. Low-volume exchanges or interactions that are naturally synchronous.
Demand window The consumer requests a quantity of work; the producer emits against that available demand. Limits outstanding demand to the window while allowing work to be pipelined. Other buffers can still accumulate work. Streams where consumers can report capacity and a bounded amount of in-flight work is useful.

Uncoordinated push

A sender can dispatch quickly because it does not wait for the recipient to complete each message. That is useful when the work is intentionally fire-and-forget, but it provides no feedback that the consumer is keeping up. If delivery must be complete, or if queued work must remain bounded, those guarantees need to come from another part of the design.

Stop-and-wait acknowledgements

Stop-and-wait adds a feedback loop: send an item, then continue only after receiving an acknowledgement tied to that item’s reference. It is straightforward and limits outstanding work in the basic example. Its cost is serialization: the sender cannot use the next item to keep the consumer busy while waiting for the current acknowledgement.

Demand windows

With demand-driven flow control, a consumer signals how many events it is ready to receive. GenStage documents that producers emit no more events than consumers have requested. A bounded demand window therefore controls one part of the flow while still allowing several items to be in flight.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Demand is not a universal cap on every queue in an application. A producer’s internal buffer, an external source’s buffer, or another stage can still hold work. Each buffer needs a limit or a clearly defined overload policy.

Using GenStage and Broadway in an Elixir pipeline

GenStage stages can be producers, consumers, or both. Consumers send demand upstream, and producers emit within that demand. The GenStage documentation recommends stages when backpressure or routing is needed, rather than adding stages merely to create concurrency. Check the documentation for the version your application uses before relying on specific APIs or defaults.

Broadway is a concurrent, multi-stage processing library built on GenStage. Its documented capabilities include backpressure, batching, acknowledgements, fault tolerance, graceful shutdown, rate-limiting, and metrics. Its architecture uses producer, processor, and batcher stages. Those features provide pipeline building blocks; they do not remove the need to decide what should happen when demand, buffers, or downstream capacity are exhausted.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

What to do when the upstream source cannot be throttled

If an external source keeps producing regardless of downstream capacity, the application has to define what happens to excess work. The right policy depends on whether completeness, freshness, or explicit feedback to the caller matters most.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Drop newest: Keep older queued work and discard arrivals that cannot be accepted. This may suit workloads where already-accepted items matter more than the latest state, but it loses new data.
  • Drop oldest: Discard older queued work to make room for fresher arrivals. This can suit workloads where the latest state is more useful than stale updates, but it sacrifices completeness.
  • Reject at the boundary: Refuse work before it enters the overloaded part of the system, such as by rejecting an HTTP request. This gives a caller a visible failure where the boundary supports it, but rejecting one request does not necessarily regulate every external source.

Choose and document the behavior in terms of the application’s delivery promise. If every item must be processed, silently dropping data is incompatible with that promise; use a design that can preserve work or report failure. If freshness matters more than a complete history, dropping stale queued updates may be an intentional trade-off.

Inspecting a queue without mistaking a snapshot for a benchmark

Elixir’s Process.info/2 can be used to inspect process information such as a queue and memory during a demonstration. The values shown in the source article are outputs from that particular experiment, not general performance guarantees or a benchmark for other systems. Queue and memory readings describe a moment; they do not, by themselves, establish how a production workload will behave over time.

The article also mentions Erlang socket active modes, but configuration advice depends on the relevant Erlang/OTP behavior and version. Consult the official documentation for the runtime and socket API in use before applying that example.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Crashes, No Sound, or Screen Glitches?Free driver scan
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.