Medium15 minDistributed Systems
UpdatedAug 6, 2026
Edit

NATS: Request-Reply Timeouts

Question Variations

  • "How should checkout handle a NATS no-responder error?"
  • "Which request-reply calls are safe to retry?"
  • "When should this interaction become an asynchronous JetStream workflow?"

Why This Is Asked

A checkout service uses NATS request-reply to ask inventory for availability, but inventory may be slow or unavailable. This tests deadline design, no-responder handling, retry safety, and the difference between an RPC path and durable event processing.

Key Concepts

  • Inbox replies: A requester uses a reply subject and waits for a bounded response.
  • Timeouts: A caller must bound waiting time and translate timeout or no-responder outcomes deliberately.
  • Retry safety: Retrying an availability query differs from retrying a reservation command with side effects.
  • Service discovery: NATS subject subscriptions decouple requesters from a fixed host address.

Question Variations

  • “How should checkout handle a NATS no-responder error?”
  • “Which request-reply calls are safe to retry?”
  • “When should this interaction become an asynchronous JetStream workflow?”

Answers by Technology

+ Add Variant
NATSImprove this answer ✏️

Expected Answer

Treat NATS request-reply as an RPC boundary. The checkout service publishes a request with an inbox reply subject and waits only until its latency budget expires. A no-responder error means no inventory service is currently subscribed; a timeout means a responder did not answer in time. Both require an explicit product decision: fail checkout, show unavailable, or move to an asynchronous reservation workflow. Retrying a read-only availability check can be safe within a short deadline. Retrying a reserve command needs an idempotency key because the first responder may have succeeded just before its reply was lost. Use JetStream rather than Core NATS when the request must survive consumer downtime or the workflow cannot finish synchronously.

Why It Matters

An unbounded request path ties checkout availability to a slow dependency. Clear timeouts and side-effect-aware retries prevent cascading failures and duplicate reservations.

Example Code

try {
  const reply = await nc.request("inventory.available", sc.encode(JSON.stringify({ sku })), { timeout: 200 });
  return JSON.parse(sc.decode(reply.data));
} catch (error) { throw new Error("inventory unavailable"); }

Common Mistakes

  • Retrying a reservation as if it were a read: A delayed first response can reserve stock twice.
  • Using Core NATS for a must-complete workflow: Offline responders cannot replay past requests.

Follow-up Questions

  • What is a no-responder result? (Answer: No active subscription matched the request subject.)
  • When use JetStream instead? (Answer: When durable delivery, recovery, or asynchronous completion is required.)

Related Questions

References