# What is Modules in NestJS

## **Understanding Modules in NestJS**

In this blog, we will discuss an essential concept in NestJS; Modules.

So far, we have been using the main module to register controllers and providers but we have not specifically explored what a module actually is in NestJS.

## **What is a Module?**

A module in NestJS is a class annotated with the `@Module()` decorator. This decorator accepts an object with four properties:

1. imports for importing other modules.
    
2. exports for exporting providers to other modules.
    
3. controllers for declaring route handlers.
    
4. providers for declaring the services or providers used in the module.
    

providers for declaring the services or providers used in the module.

You have likely seen the last two (controllers and providers) used frequently, but the full structure gives us more flexibility and modularity in our application.

## **When should you create a Module?**

You should create a new module when you want to encapsulate a set of closely related features. For example:

A UserModule might contain a UserController and a UserService.

An AlbumModule might contain an AlbumController and an AlbumService.

This structure helps you organise your codebase in a modular and scalable way.

```javascript
nest generate module users
```

This command automatically creates a new module file, which you can then connect with the relevant controller and service

## **Registering Modules**

Once you have created multiple feature modules (e.g., UserModule, AlbumModule), you must register them in the imports array of the root module:

```javascript
@Module({
   @Module({
   imports : [CatsModule, RequestModule, ResponseModule, RedirectModule]})
export class AppModule {}
```

## **Creating a Module in NestJS: Example with CatsModule**

In our cats folder, we have a file named `cats.module.ts`. Let’s walk through what we have done here and why it matters.

### **Step-by-Step Breakdown**

First, we import the necessary items from NestJS:

```javascript
import { Module } from '@nestjs/common';
import { CatsService } from './cats.service';
import { CatsController } from './cats.controller';
```

### **Creating and Exporting the Module**

Next, we define and export a class named `CatsModule`

```javascript
@Module({
  controllers: [CatsController],
  providers: [CatsService],
})
export class CatsModule {}
```

In NestJS, modules are not shared automatically across the app. If you want to use a provider from one module in another module, you need to:

1. Export it from the source module.
    
2. Import the source module into the destination module.
    

```javascript
@Module({
  providers: [CatsService],
  exports: [CatsService], // 👈 This makes it available to other modules
})
export class CatsModule {}
```

In our `CatsModule`, we’ve created a service (`CatsService`) and a controller (`CatsController`). Here's the basic module structure:

```javascript
import { Module } from '@nestjs/common';
import { CatsService } from './cats.service';
import { CatsController } from './cats.controller';

@Module({
  controllers: [CatsController],
  providers: [CatsService],
})
export class CatsModule {}
```

Now, if we run the application, you will notice the following:

NestJS first creates an instance of `CatsService`.

Then it creates an instance of `CatsController`.

This happens because `CatsController` depends on `CatsService`. So NestJS resolves dependencies from the bottom up. If a service depends on another service, that chain is resolved from the lowest level first ensuring everything is ready before the controller is instantiated.

Here’s how we inject the `CatsService` into the controller:

```javascript
constructor(private readonly catsService: CatsService) {
  console.log('CatsController instance created');
}
```

This is standard NestJS Dependency Injection (DI). The framework automatically injects the service instance into the controller.

When you add a service to the providers array of a module, NestJS creates a single instance (singleton) of that service:

This single instance is shared across all controllers in the same module.

That’s the core idea of the singleton pattern one shared instance per provider per module.

So, even if multiple controllers depend on `CatsService`, they will all receive the same instance.

Now, let’s say you try to use `CatsService` in another controller (e.g., in a RequestController inside RequestModule) like this:

```javascript
constructor(private readonly catsService: CatsService) {}
```

If you run the application without importing `CatsModule`, you’ll get an error like:  
*Nest can't resolve dependencies of the RequestController (...) CatsService at index \[0\]*  
  
This means that `CatsService` is not available in the context of RequestModule.  
NestJS modules are self contained by default. The scope of a provider is limited to the module where it is declared, unless you explicitly export it.

To fix the above error follow these steps:

**Step 1**: Export the Service from `CatsModule`:

```javascript
@Module({
  controllers: [CatsController],
  providers: [CatsService],
  exports: [CatsService], // 👈 This allows other modules to use it
})
export class CatsModule {}
```

**Step 2:** Import `CatsModule` into `RequestModule`:

```javascript
import { Module } from '@nestjs/common';
import { RequestController } from './request.controller';
import { CatsModule } from 'src/cats/cats.module';

@Module({
  controllers: [RequestController],
  imports: [CatsModule], // 👈 Import the whole module, not just the service
})
export class RequestModule {}
```

Now NestJS can resolve the dependency, and `CatsService` will be available in `RequestController`.

NestJS resolves dependencies from bottom to top resolving providers before controllers.

Providers in NestJS are singleton by default shared within the module.

A provider’s scope is limited to its module unless it is exported.

To use a provider in another module:

1. Export it from the source module.
    
2. Import the entire module (not just the provider) into the destination module.
    

This behaviour makes modules self-contained and reusable.

### **Wrapping Up**

We now understand how modules encapsulate their providers and controllers, how singleton services work, and how to properly share services between modules using exports and imports. In the future blog, we’ll explore custom provider scopes like Request, Transient, and how to build global modules.

If you’re a visual learner, check out the following video tutorial for this blog:

[https://www.youtube.com/watch?v=D83bP3mfXWE&list=PLgKb0PcT0J0SaWTrS4ZY8ATMaqLeSXgM7&index=11](https://www.youtube.com/watch?v=D83bP3mfXWE&list=PLgKb0PcT0J0SaWTrS4ZY8ATMaqLeSXgM7&index=11)

Follow us for more such content:

[https://www.linkedin.com/company/hasabtech](https://www.linkedin.com/company/hasabtech)

[https://www.youtube.com/@hasabTech](https://www.youtube.com/@hasabTech)

[https://www.instagram.com/hasab.tech/](https://www.instagram.com/hasab.tech/)

[https://www.facebook.com/hasabTech](https://www.facebook.com/hasabTech)
