Skip to content

Default mailbox: switch from unbounded to bounded (10k, drop-head) #310

Description

@pathosDev

Severity / Size

  • Severity: HIGH — unbounded default lets a runaway producer flood an actor's mailbox until OOM. Classic Akka anti-pattern; "production-ready" claim is hard to defend with this default.
  • Size: S (~2d).
  • Threat model: not an attacker — a buggy upstream actor or a transient spike in legitimate traffic.

Affected files

  • `src/util/Constants.ts` — add `DEFAULT_MAILBOX_CAPACITY` + `DEFAULT_MAILBOX_OVERFLOW` constants.
  • `src/internal/ActorCell.ts` — wire the default through when no `Props.withMailbox(...)` was supplied.
  • `src/Props.ts` — keep the explicit-unbounded escape hatch.
  • `docs/fundamentals/mailbox.mdx` (EN+DE) — explain the new default + the opt-out syntax.

Background

Currently `Mailbox.ts` defaults to an unbounded array-based `userQueue`. `BoundedMailbox` (with `drop-head` / `drop-new` / `reject` policies) exists but is purely opt-in. Operators must remember to swap it in — easy to forget, dangerous in production.

Proposed fix

  1. New constants:
    ```ts
    export const DEFAULT_MAILBOX_CAPACITY = 10_000;
    export const DEFAULT_MAILBOX_OVERFLOW: OverflowPolicy = 'drop-head';
    ```
  2. When no `mailbox` option is set on `Props`, instantiate `BoundedMailbox(DEFAULT_MAILBOX_CAPACITY, DEFAULT_MAILBOX_OVERFLOW)` instead of the current unbounded.
  3. Opt-out path stays: `Props.withMailbox(unboundedMailbox())` for legitimate cases (tests, deterministic replay).
  4. Metric `actor.mailbox.dropped` (Counter) increments on every drop-head event so operators see pressure in `/metrics` immediately.
  5. `docs/fundamentals/mailbox.mdx` (EN+DE): explain the default, show opt-out, show the metric.

Verification

  • `bun run typecheck && bun test` clean.
  • A counter actor flooded with 20k tells before its first drain emits 10k `actor.mailbox.dropped` metric ticks and processes the trailing 10k messages.
  • The `Props.withMailbox(unboundedMailbox())` escape hatch still produces an array-backed queue.

Out of scope

  • Per-actor capacity tuning (covered by `Props.withMailbox` already).
  • Switching the default overflow policy to `reject` — kept as `drop-head` because telemetry-style actors are the common case.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestpriority: highTop priority — high impact, plan next

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions