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 InjectionToken for configuration values.
  • Use useClass to swap implementations.
  • Use useFactory for runtime initialization.
  • Use multi for 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

  • useClass
  • useValue
  • useExisting
  • useFactory
  • multi

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 InjectionToken for configuration.
  • Avoid duplicate registrations.
  • Use useFactory only when needed.
  • Register providers at the appropriate scope.
  • Use standalone provider APIs in modern Angular.
  • Use multi for 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.
  • useClass replaces one implementation with another.
  • useValue injects constants and configuration values.
  • useExisting creates provider aliases.
  • useFactory supports runtime object creation.
  • multi enables multiple implementations for one token.
  • ✔ Use InjectionToken for 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