There are four forms: useClass (provide a class), useValue (provide a static value or mock), useFactory (provide the return value of a factory function — supports async and DI via the inject array), and useExisting (alias one token to another already-registered provider).
useClass — swap implementations (e.g., mock vs real service).
useValue — inject constants, config objects, or mock instances.
useFactory — when provider creation requires async work or other dependencies.
useExisting — create an alias so two tokens point to the same instance.
You're trying to inject a configuration service into a controller, but you're getting 'Cannot resolve dependency' — you've registered it as a provider but it's still not working. What are the three most likely syntax mistakes you could have made?
How would you register a simple value provider like an API key in NestJS, and what happens if you forget to include the 'provide' key?
If you use a class provider without @Injectable(), will it work? Why or why not?
A request-scoped database connection provider is causing slow responses under load — what’s likely wrong with how it’s registered, and how would you fix it?
You added a dynamic provider using forRoot() in a feature module, but now another module can’t inject it — what’s the most common mistake here, and how do you resolve it?
A factory provider returns a new instance every time, but the service using it expects state to persist — what scope mismatch is probably happening, and how do you diagnose it?
You're building a multi-tenant app where each tenant needs a different database client — how would you design dynamic providers per tenant without leaking memory or causing startup delays?
A third-party library you're wrapping requires async initialization, but your provider is used in a startup hook — how do you ensure it resolves before the app boots without blocking the entire process?
You have a provider that depends on environment variables loaded at runtime, but tests are failing because the provider tries to resolve before mocks are set — how do you restructure this to be testable and production-safe?
You're migrating a legacy NestJS monolith to microservices, and dozens of modules use custom providers with hardcoded dependencies — how do you design a migration strategy that avoids breaking changes and enables gradual replacement?
In a high-throughput system, you notice memory bloat from request-scoped providers holding references to large objects — how would you redesign the provider architecture to reduce memory pressure without sacrificing functionality?
Your team has inconsistent provider patterns across services — some use factories, others use values, and some are dynamically generated. How do you enforce consistency at the architecture level without stifling flexibility?