Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Deferrable Providers

A DeferrableServiceProvider declares which container bindings it provides via provides(). The Application skips booting it entirely until one of those bindings is actually resolved from the container — an optimization for services that aren’t always needed.

Basic usage

import { DeferrableServiceProvider, type ServiceProviderContext } from "@raubjo/architect-core"

export class ReportingProvider extends DeferrableServiceProvider {
  provides(): string[] {
    return ["reporting", "reporting.exporter"]
  }

  register({ container }: ServiceProviderContext): void {
    container.singleton("reporting", ReportingService)
    container.singleton("reporting.exporter", PdfExporter)
  }

  boot({ container }: ServiceProviderContext): void {
    // Heavy initialization only runs if "reporting" or "reporting.exporter"
    // is actually resolved
    container.make(ReportingService).connect()
  }
}

Register it the same way as any other provider:

Application.configure()
  .withProviders([new ReportingProvider()])
  .run()

When to use it

Use a DeferrableServiceProvider when:

  • The service does expensive initialization in boot() (network connections, large allocations)
  • The service is only needed on certain routes or user flows
  • You want to avoid paying boot cost for services that may never be used in a given session

When not to use it

If the service is always resolved (e.g. bound to a component that renders on every page), deferral adds overhead with no benefit. Use a regular ServiceProvider instead.

Caveats

The provides() list must be exhaustive. If a binding is registered in register() but not listed in provides(), it will be treated as undeferred and the provider will be booted eagerly.

Class-based identifiers are not supported in provides() — use string keys for deferrable bindings:

// ✅
provides() { return ["reporting"] }
register({ container }) { container.singleton("reporting", ReportingService) }

// ❌ class keys cannot be declared in provides()
provides() { return [ReportingService] }