Postboy Help

Message Family Overview

Purpose

Postboy provides three distinct message contracts to cover the communication patterns commonly found in event‑driven TypeScript applications. Rather than forcing everything through a single abstraction, each contract has a clear role:

  • PostboyGenericMessage – broadcast an event or notification.

  • PostboyCallbackMessage<T> – send a request and expect a typed response.

  • PostboyExecutor<T> – execute a controlled operation directly.

Understanding these roles helps you choose the right tool for each interaction and keeps the architecture explicit.

The three contracts at a glance

Type

Intent

Flow

PostboyGenericMessage

Something happened.

fire() → subscribers react

PostboyCallbackMessage<T>

Something happened, and I need a result.

fireCallback() → handler returns T → caller receives response

PostboyExecutor<T>

Run this operation explicitly.

exec() → registered handler runs → result returned

When to use which

PostboyGenericMessage

Use for one‑way, fire‑and‑forget communication.
Typical examples: domain events, notifications, state‑change broadcasts.

class UserCreatedEvent extends PostboyGenericMessage { static readonly ID = 'user.created'; } postboy.fire(new UserCreatedEvent('user-123'));

PostboyCallbackMessage<T>

Use when the caller depends on a response. The type parameter T describes the expected result. Typical examples: query lookups, calculations, service orchestration.

class GetUserQuery extends PostboyCallbackMessage<User | null> { static readonly ID = 'user.get'; } postboy.fireCallback(new GetUserQuery('user-123')).subscribe(user => { // use the returned user });

PostboyExecutor<T>

Use for operations that should be invoked directly, especially those that affect the bus itself or represent commands. Typical examples: adding middleware, locking messages, refreshing caches.

class LockMessages extends PostboyExecutor<void> { static readonly ID = 'bus.lock'; } await postboy.exec(new LockMessages(['user.created']));

How they relate to the base contract

All three contracts extend the abstract PostboyMessage class. This gives every message:

  • a stable identity (static ID)

  • a mutable metadata object

  • a predictable integration point for middleware and subscribers

Because they share the same foundation, the bus can treat them uniformly for tasks like tracing, logging, and middleware execution, while still distinguishing their runtime behavior based on type.

A quick comparison

Question

Answer

Should anyone react to this?

PostboyGenericMessage

Should I get a result back?

PostboyCallbackMessage<T>

Should this be executed explicitly?

PostboyExecutor<T>

What’s next

For details about the shared base contract, see PostboyMessage.

For the full lifecycle of a message (creation → publication → processing → completion/cancellation), see Message Lifecycle.

Individual chapters cover each contract in depth: PostboyGenericMessage, PostboyCallbackMessage, and PostboyExecutor.

In short

Postboy’s message family separates event‑style broadcasting, request/response flows, and explicit execution into three distinct contracts. This keeps your intent clear, your types accurate, and your bus predictable.

03 мая 2026