Concepts
Channels
Section titled “Channels”A channel is a named scope for messages. Think of it as a namespace — subscribers on the "orders" channel only see messages published to that channel.
Channels are singletons. getChannel("orders") always returns the same instance, regardless of where you call it. This means you can import getChannel in multiple modules and they’ll all share the same subscriber list.
Default channel
Section titled “Default channel”If you don’t need multiple channels, call getChannel() with no arguments:
Dispose
Section titled “Dispose”Channels can be torn down with dispose():
Disposing a channel:
- Clears all subscribers and handlers
- Rejects any pending RPC promises with
PostalDisposedError - Removes the channel from the singleton registry
- Makes subsequent
subscribe,publish,request, andhandlecalls throwPostalDisposedError
Calling dispose() on an already-disposed channel is a no-op. Unsubscribe functions returned before disposal become silent no-ops.
Topics
Section titled “Topics”Topics are dot-delimited strings that describe what a message is about:
There’s no registration step — any string works as a topic. The dots are meaningful only for wildcard matching.
Wildcards
Section titled “Wildcards”Subscription patterns support two wildcards, following the AMQP standard:
* — matches exactly one segment
Section titled “* — matches exactly one segment”# — matches zero or more segments
Section titled “# — matches zero or more segments”Combined patterns
Section titled “Combined patterns”Wildcards can appear anywhere in the pattern:
Bare wildcards
Section titled “Bare wildcards”Envelopes
Section titled “Envelopes”Every message flowing through postal is wrapped in an Envelope:
Subscribers always receive the full envelope, not just the payload. This gives you routing context without needing to thread metadata through your application.
Envelope types
Section titled “Envelope types”"publish"— Standard pub/sub message. Created bychannel.publish()."request"— RPC request. Created bychannel.request(). IncludesreplyToandcorrelationId."reply"— RPC response. Created internally byhandle(). Carries the handler’s return value and thecorrelationIdfrom the original request.
Message lifecycle
Section titled “Message lifecycle”- Publish: You call
channel.publish(topic, payload)orchannel.request(topic, payload). - Envelope creation: postal wraps the payload in an Envelope with a unique ID, timestamp, and routing fields.
- Dispatch: The envelope is matched against every subscriber’s pattern. All matches receive the envelope.
- Transports: If any transports are registered, the envelope is forwarded to remote contexts (with echo prevention).
- Wiretaps: After transports fire, registered wiretaps see the envelope.
Subscriber errors don’t stop dispatch — if one subscriber throws, the rest still execute. Errors are collected and thrown as a single AggregateError after all subscribers have been called.
Next steps
Section titled “Next steps”- Subscriptions — the full subscribe API and RPC patterns
- Wire Taps — global bus observers