NestJS — Enterprise Node.js

TypeORM Integration & Entities

16 min Lesson 20 of 30

TypeORM Integration & Entities

Most real applications need a database. TypeORM is the most popular ORM for NestJS — it maps TypeScript classes to database tables, so you work with objects instead of raw SQL. NestJS provides a dedicated @nestjs/typeorm package that integrates it cleanly with modules and dependency injection.

Connecting to the database

Install the packages and configure the connection once with TypeOrmModule.forRoot() in your root module:

// npm install @nestjs/typeorm typeorm pg import { TypeOrmModule } from '@nestjs/typeorm'; @Module({ imports: [ TypeOrmModule.forRoot({ type: 'postgres', host: 'localhost', port: 5432, username: 'app', password: 'secret', database: 'app', entities: [User], synchronize: true, // dev only — see warning below }), ], }) export class AppModule {}
Never use synchronize: true in production. It auto-alters your schema to match entities and can DROP columns or data. In production you use migrations (next lesson) for controlled, reviewable schema changes.

Defining an entity

An entity is a class decorated with @Entity(); its columns are properties decorated with column decorators:

import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn } from 'typeorm'; @Entity('users') export class User { @PrimaryGeneratedColumn() id: number; @Column({ length: 120 }) name: string; @Column({ unique: true }) email: string; @Column({ default: true }) isActive: boolean; @CreateDateColumn() createdAt: Date; }

Common column decorators

  • @PrimaryGeneratedColumn() — an auto-incrementing primary key (or 'uuid' for a UUID).
  • @Column() — a regular column, with options like type, length, nullable, unique, default.
  • @CreateDateColumn() / @UpdateDateColumn() — automatic timestamps.
  • @Index() — add a database index for faster lookups.

Registering the entity in a feature module

To use an entity's repository inside a feature, register it with forFeature():

import { TypeOrmModule } from '@nestjs/typeorm'; @Module({ imports: [TypeOrmModule.forFeature([User])], providers: [UsersService], }) export class UsersModule {}

This makes a Repository<User> injectable in that module — which is how you query and save users, covered in the next lesson.

forRoot vs forFeature: forRoot() configures the database connection once (root module); forFeature() registers specific entities' repositories for the modules that need them. You will recognise this dynamic-module pattern from earlier.

Async configuration

In a real app the connection details come from config, not hard-coded values. Use forRootAsync() to inject ConfigService:

TypeOrmModule.forRootAsync({ inject: [ConfigService], useFactory: (config: ConfigService) => ({ type: 'postgres', url: config.get('DATABASE_URL'), autoLoadEntities: true, }), });

Summary

TypeORM maps classes to tables. Configure the connection with TypeOrmModule.forRoot() (or forRootAsync() with config), define entities using @Entity() and column decorators, and register them per-feature with forFeature(). Keep synchronize off in production. Next we use the repository this generates to read and write data.