Exploring NestJS — Nest’s module system

Adam Kiss
Adam Kiss
Feb 4 · 6 min read
Photo by Jonas Smith on Unsplash

Heads up! This article is part two of the series: Exploring NestJS 🙌🏻.

You can find part one here, if you’d like: https://medium.com/javascript-in-plain-english/exploring-nestjs-installing-nestjs-and-getting-started-fb2e4f36b596.

What’s the module system, anyways?

NestJS chose to work with so-called “modules”.

A module is an isolated part of an application, which encapsulates multiple functionalities that belong together.

Usually, one module includes all the functionality needed for a business domain.

How does the module system work?

Let’s say you are building an application which has multiple users, maybe somewhere saved in the database.

Clearly, you have to access the data itself (the user data) and for this you need some files, let’s say User.entity.ts (which describes the structure of a user entity) and a service through which you do CRUD operations (create, read, update, delete): Users.service.ts.

We have to “put” both of these files in the same module: Users.module.ts, so that it’s clear they belong together.

The User entity and the Users service will be encapsulated in the same module

When another part of the application (another module) has to do with anything user-related, it knows that the Users module is the point of access.

Example: Games module can access functionalities of the Users module (like getting user details)

The root application module

Every NestJS app has a root module, called the Application module.

All the other modules are “below” this in the dependency graph of the modules.

If you don’t create any other modules in your Nest app, you will still have the default “AppModule”, which looks like this:

As you can see, a module is defined by decorating a TypeScript class with the @Module decorator.

A module is defined by its controllers, providers, exports and imports.

Let’s demystify what these mean.


A controller is a simple class annotated with the @Controller decorator.

It can respond to HTTP requests of type GET, POST, PUT etc.

We will not deep dive into them here (only in the following article), but this is how one looks:

Okay, presumed that we have this controller defined, we must now link it to the module we want to have it in.

How? We simply add the controller to the “controllers” array of the module:

We import the controller and add it to the “controllers” array of our module

Voila! We now have a controller in our module.


A really important decorator that you’ll work with in NestJS is @Injectable.

You put the code that handles business logic (all the logic of your app, accessing the database, accessing external services etc.) into Service classes.

A service class looks like this:

The @Injectable decorator is used on these service classes. It enables injecting these services into other places, for example other services that might need to communicate with it.

Coming back to our modules, we put the name of the service into our providers array. Now our service belongs to our beloved module. Yay!

We must put all our services into the “providers” array so that they belong to the module

It’s important to note that providers are not only for services.

They can be used in many other cases (related to Dependency Injection), like swapping out implementations (for testing) and so on. We will not go into details as it is not crucial to have that know-how in the beginning.


Remember our diagram from above, one module using another one?

If you’d like to expose one of the services from a module, you do this via the “exports” array of the module definition.

Example: consider a module which encapsulates all users related functionalities, let’s just call it UsersModule.

This module contains the UsersService.

If we’d like other parts of our application to access UsersService and retrieve some user data, we must export it from UsersModule.

We do it this way:

We use the “exports” array of the module to export a subset of the module’s providers

Basically, the exports array is a subset of our providers array, and specifies which providers (like Services) can be accessed and used in other modules.

Now, we have only one thing to clarify: how do we use the UsersService from within another module? This is what “imports” does.


You use the imports array to specify other modules from which you’d like to use services (or other providers).


The “imports” array of a module defined which modules’ providers you’d like to use

In the above example, we import the UsersModule in AuthModule (a module which handles authentication/ authorization — maybe we need to get some user details to see if the user has access to certain resources).

Great, but how do we actually use the services exported from UsersModule here? The answer is dependency injection:

We use NestJS’ dependency injection to inject UsersService into AuthService

We put a new field, of type UsersService, in the constructor of AuthService (part of AuthModule). This will automatically be wired via the Dependency Injection of NestJS. Elegant!

After this, we can use the functions exposed by UsersService:

We can now use the functions of the UsersService class

How do I create my own module?

You saw in Chapter 1 how to bootstrap a NestJS project.

It is really easy to create another module in your Nest app, using the Nest CLI.

Of course, you can do all the coding and wiring manually, but the CLI eases our lives.

Open a terminal window (or command prompt window) in your existing NestJS project directory and write the following:

nest generate module my-first-module

You should see the following dialog:

What did just happen?

Nest’s CLI created a new folder with the new module’s name (“my-first-module”) with the module file itself: my-first-module.module.ts:

This module is currently quite empty

As you can observe, this module is quite empty, but we’ll add some controllers and services in the next chapter of this series.

It’s also important to note that the new module was registered in the AppModule :

Looks familiar 🤔? Registration of a new module is done my importing it in the AppModule.

Congratulations 🎆! Now you should have a clear understanding of how things are structured in NestJS.


JavaScript in Plain English

Learn the web's most important programming language.

Adam Kiss

Written by

Adam Kiss

Let’s not waste time. Let’s build creative projects.

JavaScript in Plain English

Learn the web's most important programming language.

More From Medium

More from JavaScript in Plain English

More from JavaScript in Plain English

32 funny Code Comments that people actually wrote


More from JavaScript in Plain English

More from JavaScript in Plain English

How Single Page Applications Broke Web Design

More from JavaScript in Plain English

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade