← Back to Articles         
@Injectable(), providedIn, Provider, and Injector

@Injectable(), providedIn, Provider, and Injector

Published on 30 Sep 2026     7 min read Angular
Services & Dependency Injection

Angular DI: @Injectable(), providedIn, Provider, and Injector

These four concepts are closely related:

@Injectable()
     ↓
Makes the service available for DI configuration
     ↓
providedIn: 'root'
     ↓
Registers a provider with the root environment injector
     ↓
Injector resolves/creates the service
     ↓
Component receives the service

1. What is @Injectable()?

What is it?

@Injectable() is an Angular decorator that marks a class as participating in Angular's Dependency Injection (DI) system and can also configure how that class is provided.

It is most commonly used with services.

@Injectable({
  providedIn: 'root'
})
export class ProductService {
}

In simple terms:

@Injectable() tells Angular that this class can be managed through Angular's dependency injection system.


Why do we need it?

A service may itself depend on other services.

For example:

ProductService
      ↓
HttpClient

Angular DI needs the appropriate metadata/provider configuration to resolve those dependencies.

For example:

@Injectable({
  providedIn: 'root'
})
export class ProductService {

  constructor(private http: HttpClient) {
  }
}

Angular can resolve HttpClient and inject it into ProductService.


2. What does providedIn: 'root' mean?

What is it?

Consider:

@Injectable({
  providedIn: 'root'
})
export class ProductService {
}

providedIn: 'root' tells Angular to make ProductService available through the application's root environment injector.

In a typical application, this means the service is:

  • Available throughout the application
  • Created lazily when first requested
  • Shared as one instance within that injector

Conceptually:

Application
    │
Root Environment Injector
    │
    └── ProductService
           ↑
       shared instance
       /          \
Component A    Component B

Why use providedIn: 'root'?

Without it, you may need to explicitly configure a provider elsewhere.

For example:

@Component({
  selector: 'app-product',
  providers: [ProductService]
})

But this makes the provider local to that component's injector hierarchy.

For application-wide services, this is usually preferred:

@Injectable({
  providedIn: 'root'
})

Advantage: Tree-Shaking

providedIn: 'root' works well with Angular's tree-shaking.

If a service is never actually referenced, build tooling can often remove the unused service code from the final bundle.


3. What is a Provider?

What is it?

A provider is configuration that tells Angular's DI system:

When someone requests this dependency/token, how should I supply it?

Simple example:

providers: [ProductService]

This is shorthand for a provider configuration similar to:

providers: [
  {
    provide: ProductService,
    useClass: ProductService
  }
]

Here:

provide  → What dependency/token is being requested?
useClass → Which class should Angular instantiate?

Common Provider Types

Angular supports several provider configurations.

useClass

{
  provide: ProductService,
  useClass: ProductService
}

Create an instance of a class.

useValue

{
  provide: 'API_URL',
  useValue: 'https://api.example.com'
}

Provide an existing value.

In real Angular applications, an InjectionToken is generally preferable to a plain string token.

useFactory

{
  provide: ProductService,
  useFactory: () => new ProductService()
}

Create the dependency using a factory function.

useExisting

{
  provide: OldProductService,
  useExisting: ProductService
}

Make one token resolve to an already provided dependency.


4. What is an Injector?

What is it?

An injector is the Angular DI mechanism responsible for resolving dependencies from providers and returning the appropriate instances.

Suppose a component requests:

constructor(private productService: ProductService) {
}

Angular's injector effectively asks:

What does Product need?

        ↓

ProductService

        ↓

Do I have a provider for ProductService?

        ↓

Yes

        ↓

Create/retrieve ProductService

        ↓

Inject it into Product

Full Simple Sample Program

product.service.ts

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class ProductService {

  getProducts(): string[] {
    return [
      'Laptop',
      'Mobile',
      'Keyboard'
    ];
  }
}

product.ts

import { Component } from '@angular/core';
import { ProductService } from './product.service';

@Component({
  selector: 'app-product',
  standalone: true,
  templateUrl: './product.html'
})
export class Product {

  products: string[] = [];

  constructor(private productService: ProductService) {
    this.products = this.productService.getProducts();
  }
}

product.html

<h2>Products</h2>

<ul>
  @for (product of products; track product) {
    <li>{{ product }}</li>
  }
</ul>

How the Program Works

Step 1 — @Injectable()

@Injectable({
  providedIn: 'root'
})

ProductService participates in Angular DI and is configured to be provided from the root environment injector.


Step 2 — Provider

Because of:

providedIn: 'root'

Angular has provider information for:

ProductService

Conceptually:

ProductService token
       ↓
ProductService implementation

Step 3 — Component requests the service

constructor(private productService: ProductService)

The component says:

I require ProductService.

The component does not manually create it.


Step 4 — Injector resolves it

The injector searches for a provider for:

ProductService

It finds the root provider.


Step 5 — Service instance is supplied

Angular creates the service if necessary and injects it into the component.

Product Component
       │
       │ requests
       ▼
 ProductService
       │
       ▼
    Injector
       │
       │ finds
       ▼
    Provider
       │
       │ creates/resolves
       ▼
ProductService instance
       │
       ▼
Product Component

How All Four Concepts Are Connected

This distinction is very important for interviews:

Concept Meaning
@Injectable() Decorator that enables/configures a class for Angular DI
providedIn: 'root' Registers the service with the root environment injector
Provider Recipe/configuration describing how to supply a dependency
Injector DI mechanism that resolves and supplies dependencies

A simple way to remember:

@Injectable()
    ↓
"This class participates in DI"

providedIn: 'root'
    ↓
"Provide it application-wide"

Provider
    ↓
"How should I supply it?"

Injector
    ↓
"Find it, create/reuse it, and give it to the consumer"

Advantages

@Injectable()

  • Supports Angular DI.
  • Allows services to receive other dependencies.
  • Keeps dependency configuration declarative.

providedIn: 'root'

  • Simple application-wide registration.
  • Usually one shared instance.
  • Supports tree-shaking.
  • No need to manually add the service to component providers.

Providers

  • Allow implementations to be replaced.
  • Support useClass, useValue, useFactory, and useExisting.
  • Useful for testing and configuration.

Injectors

  • Automatically resolve dependencies.
  • Manage dependency instances.
  • Support hierarchical DI.
  • Reduce manual object creation.

Disadvantages / Things to Watch

Wrong provider location

If you write:

@Component({
  providers: [ProductService]
})

the component can receive a separate service instance rather than the root instance.

This matters when the service stores shared state.

Too many dependencies

A constructor like:

constructor(
  private a: ServiceA,
  private b: ServiceB,
  private c: ServiceC,
  private d: ServiceD,
  private e: ServiceE,
  private f: ServiceF
) {}

can indicate that the component/service has too many responsibilities.


Key Points

  • @Injectable() is strongly associated with services and Angular DI.
  • providedIn: 'root' provides the service through the root environment injector.
  • A provider is configuration.
  • An injector is the resolver/container mechanism.
  • Providers tell injectors how dependencies should be supplied.
  • The injector creates a service when required or returns an existing appropriate instance.
  • Angular DI is hierarchical.
  • Providing a service at different levels can create different instances.
  • providedIn: 'root' is the standard choice for many application-wide services.

Interview Questions and Answers

1. What is @Injectable()?

@Injectable() is an Angular decorator that marks/configures a class for Angular's dependency injection system. It is commonly used with services.

2. What does providedIn: 'root' mean?

It tells Angular to provide the service from the application's root environment injector, normally making one shared instance available application-wide.

3. What is a provider?

A provider is configuration that tells Angular how to create or obtain a dependency for a particular DI token.

4. What is an injector?

An injector is Angular's DI mechanism that looks up providers, creates or retrieves dependency instances, and supplies them to consumers.

5. What is the difference between a provider and an injector?

This is an important distinction:

Provider = recipe/configuration.
Injector = mechanism/container that uses that recipe to resolve the dependency.

6. Is providedIn: 'root' the same as providers: [ProductService]?

Not exactly.

@Injectable({
  providedIn: 'root'
})

provides the service at the application root level.

Whereas:

@Component({
  providers: [ProductService]
})

provides it from that component's injector and can result in a separate instance for that component subtree.

Interview Shortcut

@Injectable()       → Makes/configures class for DI

providedIn: 'root' → Root-level provider registration

Provider            → HOW to supply dependency

Injector            → RESOLVES and supplies dependency

Dependency          → WHAT the consumer needs

The most important distinction: a provider describes how to obtain an object; the injector uses providers to resolve and inject that object.

← Back to Articles