Providers — Root, Component, Module Level
Providers tell Angular HOW to create a service instance. Understand the different levels and when to use each.
Providers tell Angular HOW to create a service instance. Think of a provider as a recipe — when someone asks for a service, Angular looks at the provider to know how to make it.
In modern Angular (17+), you rarely write providers manually. The @Injectable decorator handles most cases. But understanding providers is essential for advanced scenarios.
providedIn: 'root' is the most common and recommended way to provide services. It creates ONE instance for the entire application.
Key benefits:
- Singleton — same instance everywhere
- Tree-shakeable — if no component injects it, Angular removes it from the build
- No manual registration — works without adding to any providers array
Use this for 95% of your services — API services, auth, logging, state management.
Sometimes you need each component instance to have its OWN service instance — not share it. Add providers: [] to the component decorator.
Use cases:
- Each tab/accordion needs its own state
- Each user profile card manages its own edit state
- Form wizard steps that should not share intermediate state
Child components of a component with providers will get the SAME service instance (unless they also provide their own).
Beyond simple class providers, Angular supports several provider configurations for advanced scenarios:
- useClass — substitute one class for another:
{ provide: LoggerService, useClass: ConsoleLoggerService } - useExisting — alias an existing provider:
{ provide: LoggerService, useExisting: ConsoleLoggerService } - useFactory — create instance with custom logic, includes
deps: []for dependencies - useValue — provide a direct value (string, object, etc.):
{ provide: API_URL, useValue: 'https://api.com' }
The pattern is: provide: TOKEN, use*: VALUE. What you provide and how you create it are separate concerns.
InjectionToken is for when you want to inject something that is NOT a class — strings, numbers, objects, configuration.
Why InjectionToken instead of string? Using a string token can conflict if another library uses the same string. InjectionToken creates a unique token with no naming collisions.
Common use cases: API base URLs, app configuration objects, feature flags, environment settings.
Key Takeaways
- ✅ providedIn: 'root' creates an app-wide singleton (use for 95% of services)
- ✅ Component-level providers (providers: []) create a new instance per component
- ✅ Provider configs: useClass, useExisting, useFactory, useValue for different scenarios
- ✅ InjectionToken provides unique, collision-free tokens for non-class dependencies
- ✅ Root services are tree-shakeable — removed from build if unused
Want to track your progress?
Log in to save your place and pick up where you left off.
Progress track karna chahte ho?
Login karo apni progress save karne ke liye aur jahan chhoda tha wahan se shuru karo.
Login