Postboy Help

Choosing the Right Scoping Strategy

Postboy gives you three ways to manage subscription lifecycles: registrators, namespaces, and depending services.
Each fits a different scope and complexity. This guide helps you pick the right one.

1. The three mechanisms at a glance

Mechanism

Scope

Cleanup trigger

Boilerplate

Lifetime

Registrator

Module / global

down()

Medium

Long‑lived or feature‑scoped

Namespace

Component / service

EliminateNamespace

Low

Short‑lived, tied to one class

Depending service

Service (via registrator)

down() of parent registrator

Low

Follows parent registrator

2. When to use each

Registrator

  • You have many message types (e.g., 5 or more) in a feature.

  • The scope lives for the entire application or a whole section (route, module).

  • You need centralised registration and explicit start/stop hooks.

  • You want to manage one or more IPostboyDependingService instances.

class AppRegistrator extends PostboyAbstractRegistrator { constructor(postboy: PostboyService) { super(postboy); } protected _up(): void { this.recordSubject(LocaleChangedEvent); this.recordReplay(NetworkStatusEvent); } } const appReg = new AppRegistrator(postboy); appReg.up(); // ... appReg.down(); // cleanup

Namespace

  • You have only a few messages that belong to a single component or service.

  • You want to write the subscription logic inside the class without extra files.

  • The class has a clear destroy hook (e.g., destroy(), ngOnDestroy, componentWillUnmount).

export class UserFilterService { private readonly ns = 'user-filter'; constructor(private postboy: PostboyService) { this.postboy.exec(new AddNamespace(this.ns)) .recordSubject(ApplyFilterEvent); this.postboy.sub(ApplyFilterEvent).subscribe(e => { /* ... */ }); } destroy(): void { this.postboy.exec(new EliminateNamespace(this.ns)); } }

Depending service

  • A service contains subscription logic but its lifecycle should be controlled by a parent registrator.

  • You want to reuse the service across different modules without worrying about cleanup.

  • The service’s subscriptions only make sense while the registrator is active.

class AuthService implements IPostboyDependingService { constructor(private postboy: PostboyService) { } up(): void { this.postboy.sub(UserLoginEvent).subscribe(/* ... */); } } class AppRegistrator extends PostboyAbstractRegistrator { constructor(postboy: PostboyService, auth: AuthService) { super(postboy); this.registerServices([auth]); } protected _up(): void { this.recordSubject(UserLoginEvent); } }

3. Decision flowchart

Do you need to group many message types? YES → Use a Registrator └─ Does the feature have child services with subscriptions? YES → Also register them as IPostboyDependingService NO → Are the messages local to a single class? YES → Use a Namespace NO → (edge case) Use manual unsubscription or reconsider scope

4. Mixing strategies

  • A registrator can call registerServices([...]) to activate depending services.

  • A namespace is independent; don’t try to combine it with registrators for the same messages.

  • Within a single project, it’s fine to use all three strategies in different areas as long as each scope is clear.

5. Key points

  • Registrators give the most structure; best for global and feature‑level scopes.

  • Namespaces keep things simple for small, local scopes.

  • Depending services let you decouple service logic from lifecycle wiring.

  • Always call the appropriate cleanup method (down(), .exec(new EliminateNamespace(...)), or let the parent registrator handle it).

24 апреля 2026