DEV Community

Asibul Hasan
Asibul Hasan

Posted on

Setup MonoRepo in Nest.js

Monorepos are becoming the default choice for backend teams that manage more than one service or shared library. Nest.js works very well in a monorepo setup, and it even has built-in support for it.

In this post, you’ll learn:

  • What a monorepo is and why it’s useful
  • How Nest.js supports monorepos
  • How to set up a Nest.js monorepo step by step
  • A clean folder structure that scales
  • Common tips and pitfalls

No fluff. Just what you need to get it working.


What Is a Monorepo?

A monorepo is a single repository that contains multiple applications and shared libraries.

Instead of this:

api-repo/
auth-repo/
shared-utils-repo/
Enter fullscreen mode Exit fullscreen mode

You have this:

backend/
 ├─ apps/
 └─ libs/
Enter fullscreen mode Exit fullscreen mode

Why teams use monorepos

  • Shared code lives in one place
  • Easier refactoring across projects
  • One set of tooling and configs
  • Simpler dependency management

For Nest.js projects with microservices, background workers, or shared modules, a monorepo is a natural fit.


Nest.js Monorepo Support (Built-In)

Nest.js comes with first-class monorepo support via the Nest CLI. You don’t need Nx or Turborepo to get started. The CLI can generate apps and libraries inside one workspace.

This approach is:

  • Simple
  • Official
  • Easy to maintain

Monorepo Folder Structure

Here’s the structure we’re going to build:

nest-monorepo/
├─ apps/
│  ├─ api/
│  └─ auth/
├─ libs/
│  ├─ common/
│  └─ database/
├─ nest-cli.json
├─ tsconfig.base.json
└─ package.json
Enter fullscreen mode Exit fullscreen mode

Meaning:

  • apps/ → runnable Nest.js applications
  • libs/ → shared modules, services, DTOs, helpers
  • common → filters, guards, interceptors
  • database → Prisma, TypeORM, or DB logic

Image: Nest.js Monorepo Architecture

You can include this image under the intro section.

![Nest.js Monorepo Architecture](https://your-image-url-here.com/nestjs-monorepo.png)
Enter fullscreen mode Exit fullscreen mode

Image idea:

  • One repository box
  • Inside it: apps/api, apps/auth
  • Shared libs/common and libs/database
  • Arrows showing shared usage

This visual helps readers understand the layout instantly.


Step 1: Create a New Nest.js Workspace

Make sure you have the Nest CLI installed:

npm i -g @nestjs/cli
Enter fullscreen mode Exit fullscreen mode

Create a monorepo workspace:

nest new nest-monorepo
Enter fullscreen mode Exit fullscreen mode

During setup:

  • Choose npm, yarn, or pnpm
  • Enable ESLint and Prettier if you want

Nest automatically creates a workspace-ready project.


Step 2: Enable Monorepo Mode

Open nest-cli.json:

{
  "monorepo": true,
  "root": "apps/api",
  "sourceRoot": "apps/api/src",
  "projects": {}
}
Enter fullscreen mode Exit fullscreen mode

Setting "monorepo": true tells Nest this repo will contain multiple apps and libraries.


Step 3: Create Your First App

Generate an app inside the monorepo:

nest generate app api
Enter fullscreen mode Exit fullscreen mode

Create another one:

nest generate app auth
Enter fullscreen mode Exit fullscreen mode

Now your apps/ folder looks like this:

apps/
├─ api/
└─ auth/
Enter fullscreen mode Exit fullscreen mode

Each app is a fully independent Nest.js application.


Step 4: Create Shared Libraries

Libraries are where monorepos shine.

Create a shared library:

nest generate library common
Enter fullscreen mode Exit fullscreen mode

Create a database library:

nest generate library database
Enter fullscreen mode Exit fullscreen mode

Now you have:

libs/
├─ common/
└─ database/
Enter fullscreen mode Exit fullscreen mode

Each library has:

  • Its own module
  • Its own tsconfig
  • Clean import paths

Step 5: Import a Library Into an App

Example: use CommonModule in the API app.

// apps/api/src/app.module.ts
import { Module } from '@nestjs/common';
import { CommonModule } from '@app/common';

@Module({
  imports: [CommonModule],
})
export class AppModule {}
Enter fullscreen mode Exit fullscreen mode

The @app/* alias is auto-configured by Nest.

No relative path mess. No hacks.


Step 6: Run Apps Independently

Run the API app:

nest start api
Enter fullscreen mode Exit fullscreen mode

Run the auth app:

nest start auth
Enter fullscreen mode Exit fullscreen mode

Each app:

  • Has its own port
  • Has its own environment variables
  • Can be deployed separately

Step 7: Build for Production

Build a specific app:

nest build api
Enter fullscreen mode Exit fullscreen mode

Build all apps:

nest build
Enter fullscreen mode Exit fullscreen mode

Output goes to the dist/ folder, separated by app name.


Best Practices for Nest.js Monorepos

Keep libraries small

Libraries should solve one problem. Don’t dump everything into common.

Avoid circular dependencies

If two apps depend on each other, rethink the design.

Share DTOs and interfaces

This avoids duplication and keeps APIs consistent.

One database library

Centralize database logic instead of duplicating connections.


When NOT to Use a Monorepo

A monorepo might not be ideal if:

  • You have a single small service
  • Teams are fully independent
  • Deployment pipelines are very different

For most growing backend systems, though, it’s worth it.


Final Thoughts

Nest.js monorepos are:

  • Easy to set up
  • Officially supported
  • Great for scaling backend systems

You get clean boundaries, shared code, and fewer repositories to manage. Start simple, add apps and libraries as your system grows, and keep the structure boring and predictable.

That’s what scales.


If you want, I can:

  • Add Nx on top of this
  • Convert it to a Medium-style blog
  • Create a real architecture diagram image
  • Add Docker + monorepo deployment

Just tell me.

Top comments (0)