Postboy Help

Best Practices & Anti‑patterns

This section collects practical recommendations for using Postboy’s lifecycle management features effectively. Following these guidelines helps keep your message‑driven code clean, predictable, and free of memory leaks.

Best Practices

1. Always call the cleanup function

Every scoping mechanism has a dedicated cleanup trigger. Make sure it is called when the owning component, service, or module is destroyed.

Mechanism

Cleanup trigger

Registrator

down()

Namespace

EliminateNamespace

Depending service

down() on parent registrator

2. Use unique namespace names

A namespace string must be unique across your application. If multiple instances of the same class exist, append an identifier.

// ✅ safe: unique per instance const ns = `user-filter-${uniqueId()}`; this.postboy.exec(new AddNamespace(ns)).recordSubject(ApplyFilterEvent);

3. Keep scoping close to the owner

Register messages and subscriptions inside the class that owns their lifecycle. Avoid spreading namespace creation or registrator setup across unrelated files.

4. Choose the simplest mechanism for the job

  • One or two messages in a single class? → Namespace.

  • Entire feature with many messages? → Registrator.

  • Service logic that depends on a parent registrator?IPostboyDependingService.

Avoid creating a full registrator for a single event.

5. Test handlers independently

Both registrators and namespace callbacks should contain minimal logic. Delegate business rules to plain functions or handler classes that can be tested without the bus.

6. Keep message contracts small

Each message should carry only the data needed to describe what happened or what is requested. Do not use messages as generic data containers.

Anti‑patterns

1. Forgetting to clean up

// ❌ namespace created, never eliminated constructor(postboy: PostboyService) { postboy.exec(new AddNamespace('my-ns')).recordSubject(SomeEvent); }

If a namespace is not eliminated, its subscriptions live forever. Always pair AddNamespace with a corresponding EliminateNamespace in a destructor.

2. Using one global namespace for everything

// ❌ anti‑pattern: all messages in one namespace postboy.exec(new AddNamespace('app')) .recordSubject(EventA) .recordSubject(EventB)... ;

A single namespace defeats the purpose of scoping — you lose the ability to clean up only a subset of subscriptions.

3. Mixing registration strategies in one place

// ❌ avoid mixing registrator and namespace for the same messages class MyService { private ns = 'my-service'; constructor(private postboy: PostboyService, private reg: MyRegistrator) { // mixing scopes creates confusion about who owns the subscription } }

Choose one strategy per message set and stick to it.

4. Creating a registrator for trivial cases

// ❌ registrator for a single subscription class SingleEventRegistrator extends PostboyAbstractRegistrator { _up() { this.recordSubject(SingleEvent); } }

Registrators add structure; for a single event, a namespace is simpler and just as safe.

5. Relying on manual unsubscription

// ❌ manual bookkeeping const subs: Subscription[] = []; subs.push(postboy.sub(EventA).subscribe(/* ... */)); // cleanup subs.forEach(s => s.unsubscribe());

Postboy’s scoping mechanisms exist to eliminate manual subscription arrays. Use them instead of raw unsubscribe() calls.

6. Subscribing in the constructor without order guarantees

// ❌ may fail if UserLoginEvent is not yet registered class AuthService { constructor(private postboy: PostboyService) { this.postboy.sub(UserLoginEvent).subscribe(/* ... */); } }

If AuthService is instantiated before the registrator that owns UserLoginEvent, this code throws. Use IPostboyDependingService to delay subscription until the bus is ready.

Summary

  • Always call the cleanup trigger for every scope you create.

  • Use unique, descriptive names for namespaces.

  • Match the scoping strategy to the size and lifetime of the feature.

  • Keep message handlers and contracts focused.

  • Let Postboy manage subscription lifecycles — do not revert to manual unsubscribe arrays.

07 мая 2026