Application¶
WakuApplication is the runtime object that holds the DI container, module registry, and extension registry.
It is created by WakuFactory from a root module and used as an async context manager
to manage the full application lifecycle.
WakuFactory¶
WakuFactory takes a root module and produces a WakuApplication. Under the hood it:
- Builds a
ModuleRegistry(topological sort of all imported modules) - Builds a Dishka
AsyncContainerfrom the collected providers - Builds an
ExtensionRegistryfrom application and module extensions - Returns a ready-to-use
WakuApplication
Parameters¶
| Parameter | Type | Description |
|---|---|---|
root_module_type |
ModuleType |
The root module class (positional-only). Serves as the composition root of the application graph. |
context |
dict[Any, Any] | None |
APP-level context dict for contextual providers. See Container Access. |
lifespan |
Sequence[LifespanFunc] |
Lifespan functions for setup/teardown of long-lived resources. |
extensions |
Sequence[ApplicationExtension] |
Application-level extensions. Defaults to DEFAULT_EXTENSIONS. |
container_config |
ContainerConfig | None |
Container configuration (see below). |
ContainerConfig¶
ContainerConfig controls the underlying Dishka container behavior:
| Field | Default | Description |
|---|---|---|
lock_factory |
asyncio.Lock |
Factory for the concurrency lock used by the container. |
start_scope |
None |
Starting scope for the container. None means the first one. |
skip_validation |
False |
Skip provider graph validation at startup. |
Bootstrap Function¶
Wrap WakuFactory in a dedicated bootstrap function rather than
calling the factory inline. This gives you a single entrypoint for application creation that
you then pass down to framework-specific factory methods (API server, CLI, message broker, etc.):
Each entrypoint calls the bootstrap function and passes the resulting application to its own framework bootstrap:
- Framework-specific factory that wires the
WakuApplicationinto FastAPI, Litestar, FastStream, etc. using the corresponding Dishka integration.
This keeps module composition and factory configuration in one place. When you add a new module import, change the context shape, or swap an extension, every runner picks up the change automatically.
Application Lifecycle¶
WakuApplication implements the async context manager protocol. Use async with to manage
the full startup/shutdown sequence:
flowchart TD
S1["Extensions init hooks"] --> S2["Lifespan functions enter"]
S2 --> S3["Container context enter"]
S3 --> R(["Application runs"])
R --> E1["Extensions shutdown hooks"]
E1 --> E2["Container context exit"]
E2 --> E3["Lifespan functions exit"]
Execution order¶
Startup (entering async with app):
- Extension init hooks run (
OnModuleInit,OnApplicationInit,AfterApplicationInit) - Lifespan functions are entered in the order they were provided
- The DI container context is entered
Shutdown (exiting async with app):
- Extension shutdown hooks run (
OnModuleDestroy,OnApplicationShutdown) - The DI container context is exited
- Lifespan functions are exited in reverse order (LIFO)
For details on extension hooks, see Lifecycle Hooks.
Lifespan¶
Lifespan functions handle setup and teardown that must happen outside the container lifecycle — database migrations, service discovery registration, signal handlers, or background schedulers.
Tip
For long-lived resources like connection pools, HTTP clients, or cache connections, prefer singleton providers instead. The container already manages their lifecycle — creating them on first request and finalizing them on shutdown.
Waku accepts two forms of lifespan function, unified under the LifespanFunc type alias:
-
A callable that receives the application and returns an async context manager:
-
A bare async context manager (when you do not need access to the application instance):
Both forms are wrapped internally by LifespanWrapper, so you never need to instantiate it yourself.
Pass your lifespan functions to WakuFactory via the lifespan parameter:
Container Access¶
The container property on WakuApplication returns the Dishka AsyncContainer.
Context values can be provided at two levels, corresponding to Dishka's scopes:
APP-level context¶
Pass context to WakuFactory to make values available in Scope.APP.
Use this for application-wide data that is known at startup — configuration objects,
environment identifiers, or feature flags:
REQUEST-level context¶
Call app.container(context={...}) to create a child scope with Scope.REQUEST context.
Use this for per-request data — HTTP requests, user sessions, or message payloads:
Tip
For declaring contextual dependencies, see Contextual providers. For a deeper dive into Dishka scopes, see the Dishka scopes documentation.
Further reading¶
- Lifecycle Hooks — extension hooks that run during application startup and shutdown
- Modules — module system and the
@module()decorator - Framework Integrations — connecting waku to FastAPI, Litestar, and other frameworks
- Testing — test utilities and provider overrides