Skip to main content
Providers are the services, repositories, and utilities that your application logic depends on. In nestrs, any type can become a provider by implementing the Injectable trait — the #[injectable] proc-macro generates that implementation for you. The framework constructs and caches providers in the ProviderRegistry, then makes them available to controllers and other providers through Axum’s State extractor.

Marking a type as injectable

Apply #[injectable] to a struct to generate the Injectable trait implementation. nestrs calls construct to build the type, injecting any dependencies it finds in the registry:
nestrs infers dependencies from the struct fields. Any field of type Arc<T> where T is a registered provider is resolved from the registry automatically.
construct is synchronous. Do not call block_on or perform I/O inside it — use on_module_init for async setup.

Provider scopes

Control how long a provider instance lives with the scope argument:

Registering providers in a module

List your providers in the providers field of the enclosing module. Providers that other modules need must also appear in exports:
To share a provider across modules:

Injecting providers into controllers

Controllers access their providers via Axum’s State extractor. The #[routes(state = T)] macro wires the service type into the router:

Injecting providers into other providers

When one provider depends on another, declare the dependency as an Arc<T> field and ensure both types are registered in the same module (or that the dependency is exported from an imported module):

Lifecycle hooks

Injectable provides four async hooks (all default to no-ops):
Lifecycle hooks only run for singleton providers. Transient providers are constructed on demand and do not receive hook calls.

Custom factory providers

Use register_use_factory when construction order must be explicit or when you need to close a provider dependency cycle without calling registry.get() eagerly inside another type’s construct:

All custom provider variants

Keep factory closures non-async. Defer I/O to on_module_init on the produced type, or to ConfigurableModuleBuilder::for_root_async for module-level configuration.