Bind Before You Call Your Own Service
Table of Contents
+#+created: 2026-10-14 +#+updated: 2026-10-14 +#+pattern_group: ownership
This page defines the nats pattern Bind Before You Call Your Own Service in the NATS service patterns language. It is the mechanism that makes Service Bootstrap Phases safe.
1. Also known as
- The two-phase bootstrap; wiring before readiness activities.
2. Context
A service's startup does two different kinds of thing: it wires subjects to handlers, and it does work that itself needs a subject — minting its service token, warming a cache, reading a bootstrap status. The second kind calls a subject, and some of those subjects belong to the service itself.
3. Problem
In what order may a service register handlers and call subjects, when some of the subjects it calls are its own?
4. Forces
- Dispatch is on its own thread, so a subject is callable the instant it is subscribed.
- A service that calls its own subject before registering the handler waits out a timeout.
- With several replicas, another replica may answer; a single-replica development environment has no one else to answer.
- The failure looks like a hung service, not an ordering bug.
5. Solution
Two phases, in this order: register every subscription, then do everything that calls a subject.
// Phase 1 — wire every subject. Nothing here calls a subject. auto subs = messaging::registrar::register_handlers(nats, ctx, signer); // Phase 2 — everything that calls a subject, including our own. warm_the_cache(nats); // safe only because phase 1 finished mint_the_service_token(nats); announce_ready(); // ... run until signalled ... nats.drain();
Three rules:
- Register first, call second. No call to any subject before the last subscription is registered.
- A self-call is still a call. A subject the service itself answers obeys the same rule as a subject another service answers.
- The order is the structure, not a comment. Phase 1 is one call that returns the handles; phase 2 is what follows it.
6. Failure handling
#+ATTR_HTML
| Concern | What the pattern does |
|---|---|
| Errors | A self-call in the wrong phase does not error; it waits out the request deadline and reports a timeout. |
| Timeouts | The symptom of the wrong order is a request timeout at startup, with a subscriber that looks healthy. |
| Retries | Retrying does not help: the handler will never be registered yet. |
| Idempotency | Registration is idempotent per process; the phases are about order, not repetition. |
| Observability | The handler registration lines precede any request line, so the order is visible in the log. |
7. Pitfalls
- Warming a cache before registering. The service waits out a deadline against itself and may exit as unhealthy.
- Working in development, failing under load. Another replica answers the self-call, so the bug hides until a single-replica environment.
- Minting a token inside the registration path. The registration is now a call, and the phases have merged.
- Registering after readiness. A caller that reaches the service in between gets no responders.
8. Resulting context
- Benefits
- Startup has no ordering hazard, and a subject is either not advertised or callable.
- Liabilities
- Anything that needs a subject must be expressed as phase 2 work rather than as part of wiring.
9. In ORE Studio
The service runner registers handlers and keeps the returned handles, then performs readiness activities such as minting the service token or warming a cache, then drains on shutdown. The party-cache self-login case is the worked example of the order mattering.
10. Related patterns
- Own the Subscription Handle — the handles phase 1 returns.
- Queue-Group Subscription — what a self-call races against.
11. Sources
- Service Bootstrap Phases — the ORE Studio statement of this ordering.
- microservices.io, Service Instance per Host and the microservices.io catalogue on service startup and discovery.
12. See also
- NATS service patterns — the structure note that orders this pattern language, and where to read this page in it.