KubeMQ
ConnectorsAMQP 1.0How-to guides

Flow Control

AMQP 1.0 link credit on KubeMQ — who grants credit on produce vs consume links, prefetch and MaxUnsettledPerLink, drain, and pre-settled data-loss footguns.

In AMQP 1.0, link credit is what publisher confirms and consumer prefetch/QoS are in other protocols: it is the unit of flow control. A sender may not transmit a TRANSFER until the receiver has granted link-credit > 0 via a FLOW. This guide is the practical playbook for driving the KubeMQ AMQP 1.0 connector's credit machinery — and, first and foremost, for avoiding the two ways credit mismanagement silently loses data.

For the conceptual credit model, see the Events and Events Store pattern pages.

The two data-loss footguns — read this first

These are the two most expensive mistakes you can make against this connector. Both lose messages silently — no error, no DISPOSITION, no DETACH (footgun A) — because the events and events-store patterns deliver pre-settled (at-most-once). Internalize them before you write a subscriber.

Footgun A — Events at 0 credit are silently DROPPED. On an events/<ch> consume link, a message that arrives while your link-credit is 0 is silently dropped and counted — there is no error and no DISPOSITION. This is true at-most-once: the message is simply gone. It bites a slow consumer that lets its credit drain, or a subscriber that attaches after a publish (events have no replay). Defense: grant credit continuously. Open the receiver with a healthy standing credit and replenish eagerly, well before it hits 0. Watch kubemq_amqp10_events_dropped_no_credit_total — a non-zero value is silent data loss.

Footgun B — Events-Store stalled credit loses the buffered, already-acked window. An events-store/<ch> consume link fronts the durable subscription with a deliver-first ring buffer (cap MaxUnsettledPerLink ≈ 1024) so the broker callback never stalls. The buffer's positions are auto-acked before you take delivery. If the buffer fills while your credit stays at 0, the link DETACHes with amqp:resource-limit-exceeded ("credit stalled") and the entire buffered window — already auto-acked — is lost; a durable re-attach resumes after it. Defense: size MaxUnsettledPerLink to your real prefetch and replenish credit aggressively so the buffer never fills with credit at zero. The lost window is counted in kubemq_amqp10_events_store_dropped_stalled_total.

Why queues are safe by contrast. A queue consume link never drops on low credit: when you stop granting, KubeMQ simply stops delivering and the messages wait in the queue. The drop footguns are specific to the pre-settled pub/sub patterns (events, events-store).

Who grants credit — the rule that governs everything

The single most important distinction: on a consume (server-sender) link, YOU must grant credit; on a produce (server-receiver) link, the server grants credit.

Your linkServer roleWho grants creditIf credit is 0…
Receiver from <pattern>/<ch> (you consume)server-senderyou (the client) must FLOW link-credit > 0queues: delivery pauses, messages wait. events: dropped (footgun A). events-store: buffered then stalled-DETACH (footgun B)
Sender to <pattern>/<ch> (you produce)server-receiverthe server grants you credityou may not TRANSFER until you receive the server's FLOW

Produce path — the server grants you credit

On attach, a server-receiver link immediately emits a FLOW granting link-credit = MaxUnsettledPerLink (default 1024, clamped [1, 1<<20]; fallback 256 if unset). You MUST NOT send a TRANSFER before you receive that credit. As you complete deliveries the server replenishes the window (a fresh FLOW) when remaining credit falls below half, so a steady producer never stalls. The session incoming-window (2048) is a secondary bound.

Consume path — you grant the server credit

A server-sender link delivers nothing until you send a FLOW with link-credit > 0. The effective credit the server may use is (flow.delivery-count + flow.link-credit) − server.delivery-count, clamped ≥ 0.

  • For automatic credit, grant a modest standing credit (e.g. 100–1000, but MaxUnsettledPerLink = 1024) when you open the receiver, and let your client replenish on settlement.
  • For manual credit control (IssueCredit / DrainCredit), open the receiver with Credit: -1 — otherwise your client auto-manages credit and your manual calls fight it.

These three knobs shape how the connector pulls from the broker and how much it will hold unsettled:

KnobDefaultMeaning
link-credit (prefetch)you choosethe standing credit you grant a consume link = your prefetch depth
GetBatchSize32the per-Get ceiling on a queue consume link
MaxUnsettledPerLink1024the per-link unsettled / pub-sub buffer cap; also drives the inbound (produce) credit window

For a queue consume link, each Get reserves min(credit, GetBatchSize=32, MaxUnsettledPerLink − unsettled) and issues a downstream Get with a 1000 ms long-poll. So even with high standing credit, a single Get pulls at most 32 messages — credit controls overall in-flight depth, GetBatchSize controls batch granularity.

MaxUnsettledPerLink is the dial that protects you from footgun B — it is the events-store ring-buffer cap. It is a server config field (CONNECTORS_AMQP10_MAX_UNSETTLED_PER_LINK); you respect it client-side by keeping your standing credit ≤ it and replenishing eagerly. See Configuration.

Drain

Drain is how a consumer says "give me everything you have, then stop." Send a FLOW with drain=true. The server then:

  1. advances delivery-count by the remaining credit,
  2. zeroes the credit, and
  3. echoes a FLOW with link-credit=0, drain=true (the drain response).

Drain completes promptly — it does not hang. A held remainder (messages that didn't fit the drained credit) resumes on a fresh IssueCredit. Two requirements your client must honor:

  • A FLOW MUST carry next-incoming-id once the session is established.
  • To drive drain manually, the receiver must be in manual-credit mode (Credit: -1).

Putting it together

PatternConsume-side credit hygiene
QueuesSafe: grant standing credit; if you stop granting, messages wait. No drop.
EventsFootgun A. Grant generous standing credit, replenish before it hits 0, subscribe before publishing. A gap at 0 credit = silent loss.
Events-StoreFootgun B. Size MaxUnsettledPerLink to your prefetch; replenish aggressively. A genuine stall overflows the deliver-first buffer and loses the already-acked window.
Commands / Queries (RPC)The responder pump runs under credit; grant the responder credit and grant the dynamic reply node credit so replies can land.

Monitoring

Watch these metrics — a non-zero value on the first two is silent data loss:

MetricMeaning
kubemq_amqp10_events_dropped_no_credit_totalFootgun A — events dropped at 0 credit
kubemq_amqp10_events_store_dropped_stalled_totalFootgun B — events-store buffered window lost to a credit stall
kubemq_amqp10_transfers_in_dropped_totalinbound transfers dropped (oversize / no-consumer / pre-settled failure)

See Connections endpoint for the full metric and dashboard surface.

Was this page helpful?

On this page