Angular Providers
Master Angular Providers with detailed explanations of provider types, useClass, useValue, useExisting, useFactory, InjectionToken, hierarchical providers, standalone providers, architecture diagrams, enterprise examples, and interview questions.
A Provider tells Angular how to create or supply a dependency.
When a component, directive, pipe, or service requests a dependency, Angular looks for a matching Provider in the Injector hierarchy.
Providers are one of the core concepts behind Angular Dependency Injection (DI) and are frequently asked in Angular interviews.
Table of Contents
- What are Providers?
- Why Providers?
- How Providers Work
- Provider Registration
- Provider Types
- useClass
- useValue
- useExisting
- useFactory
- Multi Providers
- InjectionToken
- Hierarchical Providers
- Standalone Providers
- Enterprise Example
- Performance Best Practices
- Top 10 Interview Questions
- Summary
What is a Provider?
A Provider tells Angular:
- Which dependency to create
- How to create it
- When to create it
- Which implementation should be injected
Without Providers, Angular doesn't know how to satisfy a dependency.
Provider Architecture
flowchart LR
Component
Component --> Injector
Injector --> Provider
Provider --> Service
Service --> Component
Why Do We Need Providers?
Without Providers
Component
↓
new UserService()
↓
Tight Coupling
With Providers
Component
↓
Injector
↓
Provider
↓
Service
Benefits
- Loose coupling
- Better testing
- Flexible implementations
- Easier maintenance
- Better scalability
Dependency Resolution Flow
sequenceDiagram
participant Component
participant Injector
participant Provider
participant Service
Component->>Injector: Need UserService
Injector->>Provider: Find Provider
Provider->>Service: Create or Return Instance
Service-->>Component: Inject Service
Registering Providers
Root Provider
@Injectable({
providedIn: 'root'
})
export class UserService {}
Application-wide singleton.
Component Provider
@Component({
selector: 'app-user',
providers: [UserService]
})
export class UserComponent {}
Each component instance receives its own UserService.
Standalone Bootstrap Provider
import { bootstrapApplication } from '@angular/platform-browser';
import { provideHttpClient } from '@angular/common/http';
bootstrapApplication(AppComponent, {
providers: [
provideHttpClient()
]
});
Provider Resolution
flowchart TD
Component
Component --> ComponentInjector
ComponentInjector --> Found
ComponentInjector --> ParentInjector
ParentInjector --> RootInjector
RootInjector --> Service
Angular searches from the closest injector upward.
Provider Types
Angular supports several provider configurations.
| Provider | Purpose |
|---|---|
| useClass | Create a class instance |
| useValue | Inject a constant value |
| useExisting | Alias another provider |
| useFactory | Create dynamically |
| multi | Multiple implementations |
useClass Provider
The default provider type.
providers: [
{
provide: LoggerService,
useClass: ConsoleLoggerService
}
]
Angular creates an instance of ConsoleLoggerService whenever LoggerService is requested.
useClass Flow
flowchart LR
LoggerService
LoggerService --> useClass
useClass --> ConsoleLoggerService
ConsoleLoggerService --> Component
useValue Provider
Inject constant values.
providers: [
{
provide: 'API_URL',
useValue: 'https://api.company.com'
}
]
Better with InjectionToken.
export const API_URL =
new InjectionToken<string>('API_URL');
providers: [
{
provide: API_URL,
useValue: 'https://api.company.com'
}
];
Inject
constructor(
@Inject(API_URL)
private apiUrl:string
){}
useValue Architecture
flowchart LR
InjectionToken
InjectionToken --> useValue
useValue --> Configuration
Configuration --> Component
useExisting Provider
Creates an alias.
providers:[
{
provide:OldLogger,
useExisting:LoggerService
}
]
Both tokens refer to the same service instance.
useExisting Flow
flowchart LR
OldLogger
OldLogger --> LoggerService
LoggerService --> Singleton
Singleton --> Component
useFactory Provider
Create objects dynamically.
export function loggerFactory() {
return new LoggerService();
}
Provider
providers:[
{
provide:LoggerService,
useFactory:loggerFactory
}
]
Factory with Dependencies
export function apiFactory(
config: ConfigService
): ApiService {
return new ApiService(config.apiUrl);
}
providers: [
{
provide: ApiService,
useFactory: apiFactory,
deps: [ConfigService]
}
];
Useful for runtime configuration.
Factory Architecture
flowchart TD
Injector
Injector --> Factory
Factory --> ConfigService
Factory --> LoggerService
Factory --> ApiService
Multi Providers
Allow multiple implementations for the same token.
Example
providers:[
{
provide:HTTP_INTERCEPTORS,
useClass:AuthInterceptor,
multi:true
},
{
provide:HTTP_INTERCEPTORS,
useClass:LoggingInterceptor,
multi:true
},
{
provide:HTTP_INTERCEPTORS,
useClass:CacheInterceptor,
multi:true
}
]
Angular injects an array of interceptors.
Multi Provider Flow
flowchart LR
HTTPRequest
HTTPRequest --> AuthInterceptor
AuthInterceptor --> LoggingInterceptor
LoggingInterceptor --> CacheInterceptor
CacheInterceptor --> Server
InjectionToken
Use an InjectionToken for interfaces, configuration values, and other non-class dependencies.
export const APP_CONFIG =
new InjectionToken<AppConfig>(
'APP_CONFIG'
);
Provider
providers:[
{
provide:APP_CONFIG,
useValue:{
apiUrl:'https://api.company.com',
timeout:30000
}
}
]
Inject
constructor(
@Inject(APP_CONFIG)
private config:AppConfig
){}
Why InjectionToken?
Interfaces do not exist at runtime.
interface PaymentService{}
Angular cannot inject interfaces directly.
Use
const PAYMENT_SERVICE =
new InjectionToken<PaymentService>(
'PAYMENT_SERVICE'
);
Provider Hierarchy
flowchart TD
RootInjector
RootInjector --> FeatureInjector
FeatureInjector --> ComponentInjector
ComponentInjector --> DirectiveInjector
Providers follow Angular's hierarchical dependency resolution.
Overriding Providers
Parent
@Component({
providers:[
LoggerService
]
})
Child
@Component({
providers:[
LoggerService
]
})
The child receives its own LoggerService instance.
Standalone Provider APIs
Modern Angular includes provider helper functions.
bootstrapApplication(AppComponent,{
providers:[
provideHttpClient()
]
});
Additional examples include:
import { provideRouter } from '@angular/router';
import { provideAnimations } from '@angular/platform-browser/animations';
bootstrapApplication(AppComponent, {
providers: [
provideRouter(routes),
provideAnimations()
]
});
Benefits
- Better tree shaking
- Cleaner configuration
- Modern Angular architecture
Enterprise Banking Example
A banking application uses:
- Authentication
- Logging
- Payments
- Notifications
- HTTP Interceptors
Architecture
flowchart TD
BankDashboard
BankDashboard --> AuthService
BankDashboard --> PaymentService
BankDashboard --> LoggerService
BankDashboard --> NotificationService
PaymentService --> RESTAPI
LoggerService --> Monitoring
NotificationService --> Email
RESTAPI --> BankServer
Provider Configuration
providers:[
AuthService,
PaymentService,
NotificationService,
{
provide:LoggerService,
useClass:CloudLoggerService
}
]
Real-World Provider Scenarios
| Scenario | Provider Type |
|---|---|
| Replace Logger | useClass |
| API URL | useValue |
| Runtime Configuration | useFactory |
| HTTP Interceptors | multi |
| Legacy Alias | useExisting |
| Configuration Object | InjectionToken |
Performance Best Practices
| Practice | Benefit |
|---|---|
Use providedIn:'root' |
Tree shaking and singleton services |
Use InjectionToken |
Safe configuration injection |
Use useFactory only when necessary |
Simpler provider graph |
| Avoid duplicate providers | Prevent unnecessary instances |
| Register providers at the correct scope | Better memory utilization |
| Prefer standalone provider APIs | Modern Angular configuration |
Common Mistakes
Using Strings Instead of InjectionToken
❌
provide:'API_URL'
Prefer
provide:API_URL
where API_URL is an InjectionToken.
Duplicate Providers
Registering the same service in multiple component providers may unintentionally create multiple instances.
Using useFactory Unnecessarily
Use useFactory only when runtime logic or dependency-based construction is required.
Forgetting multi:true
provide:HTTP_INTERCEPTORS
Without multi: true, one interceptor registration can replace another instead of contributing to the interceptor chain.
Best Practices
- Prefer
providedIn: 'root'for shared services. - Use
InjectionTokenfor configuration values. - Use
useClassto swap implementations. - Use
useFactoryfor runtime initialization. - Use
multifor extensible pipelines like HTTP interceptors. - Keep providers close to the scope where they are needed.
- Prefer standalone provider APIs in new Angular applications.
Advantages
| Feature | Benefit |
|---|---|
| Flexible DI | Multiple implementations |
| Loose Coupling | Easier maintenance |
| Tree Shaking | Smaller bundles |
| Scoped Providers | Better isolation |
| InjectionToken | Type-safe configuration |
| Multi Providers | Extensible architecture |
Top 10 Angular Providers Interview Questions
1. What is an Angular Provider?
Answer
A Provider tells Angular how to create, configure, or supply a dependency requested through the Dependency Injection system.
2. What is the difference between a Provider and an Injector?
| Provider | Injector |
|---|---|
| Defines how to create a dependency | Resolves and supplies dependencies |
| Configuration | Runtime container |
3. What are the different provider types?
Answer
useClassuseValueuseExistinguseFactorymulti
4. When should you use useClass?
Answer
Use useClass when replacing one implementation with another implementation of the same service contract.
5. When should you use useValue?
Answer
Use useValue to inject constants or configuration objects, typically together with an InjectionToken.
6. What is useExisting?
Answer
useExisting creates an alias so multiple provider tokens resolve to the same service instance.
7. When should useFactory be used?
Answer
Use useFactory when dependency creation requires runtime logic, configuration, or other injected dependencies.
8. What are Multi Providers?
Answer
Multi Providers allow multiple implementations to be registered for the same token. Angular injects them as an array.
A common example is HTTP_INTERCEPTORS.
9. Why should InjectionToken be used?
Answer
InjectionToken enables Angular to inject interfaces, configuration objects, primitive values, and other non-class dependencies that do not exist at runtime.
10. What are the best practices for Angular Providers?
Answer
- Prefer
providedIn: 'root'. - Use
InjectionTokenfor configuration. - Avoid duplicate registrations.
- Use
useFactoryonly when needed. - Register providers at the appropriate scope.
- Use standalone provider APIs in modern Angular.
- Use
multifor extensible provider chains.
Interview Cheat Sheet
| Topic | Remember |
|---|---|
| Default Provider | useClass |
| Constant Values | useValue |
| Alias | useExisting |
| Dynamic Creation | useFactory |
| Multiple Implementations | multi:true |
| Configuration | InjectionToken |
| Singleton | providedIn:'root' |
| Bootstrap Providers | provideHttpClient() |
| Common Multi Provider | HTTP_INTERCEPTORS |
| Best Practice | Register at the correct scope |
Summary
Angular Providers are the configuration layer of the Dependency Injection system. They define what dependency should be supplied and how Angular should create or retrieve it. By understanding provider types such as useClass, useValue, useExisting, useFactory, and multi, developers can build flexible, maintainable, and highly configurable Angular applications. Modern Angular further simplifies provider configuration through standalone APIs and tree-shakable services.
Key Takeaways
- ✔ Providers configure Angular's Dependency Injection system.
- ✔
useClassreplaces one implementation with another. - ✔
useValueinjects constants and configuration values. - ✔
useExistingcreates provider aliases. - ✔
useFactorysupports runtime object creation. - ✔
multienables multiple implementations for one token. - ✔ Use
InjectionTokenfor non-class dependencies. - ✔ Register providers at the appropriate scope.
- ✔ Prefer standalone provider APIs in modern Angular.
- ✔ Angular Providers are a fundamental interview topic.
Next Article
➡️ 34-Services-in-Angular-QA.md