Skip to content

NestJS TypeORM

TypeORM is NestJS's most common SQL ORM integration. This lesson covers configuring TypeOrmModule, defining entities, and injecting repositories into services.

Installing and Configuring TypeORM

@nestjs/typeorm wraps TypeORM so entities and repositories participate in Nest's DI container. You configure a root connection once, then import feature repositories where needed.

import { TypeOrmModule } from '@nestjs/typeorm';

TypeOrmModule.forRoot({
  type: 'postgres',
  host: 'localhost',
  port: 5432,
  username: 'nest',
  password: 'secret',
  database: 'nest',
  autoLoadEntities: true,
  synchronize: false,
})

autoLoadEntities: true registers entities from feature modules automatically. Keep synchronize: false in production and use migrations instead.

Entity and Repository Usage

@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column({ unique: true })
  email: string;
}

@Injectable()
export class UsersService {
  constructor(
    @InjectRepository(User)
    private readonly usersRepo: Repository<User>,
  ) {}

  findAll() {
    return this.usersRepo.find();
  }
}
  • @Entity() maps a class to a database table.
  • @InjectRepository(Entity) injects TypeORM's Repository<T> for that entity.
  • TypeOrmModule.forFeature([User]) must be imported in the feature module.
  • Repository methods like find, findOneBy, save, and delete cover most CRUD cases.

TypeORM Nest Cheatsheet

Core TypeORM patterns inside Nest modules.

API Purpose
TypeOrmModule.forRoot() Configure the database connection
TypeOrmModule.forFeature([Entity]) Register repositories for a module
@InjectRepository(Entity) Inject a repository into a provider
Repository.find() Load rows with optional filters
Repository.save() Insert or update an entity
QueryRunner Run multi-step SQL transactions

Defining Relations

TypeORM supports @OneToMany, @ManyToOne, @ManyToMany, and join tables. Prefer explicit relations options (or QueryBuilder joins) when loading related data to avoid N+1 query issues.

@ManyToOne(() => Organization, (org) => org.users)
organization: Organization;

Migrations Instead of Synchronize

synchronize: true auto-alters the schema from entities and is convenient for local experimentation, but dangerous in production. Use TypeORM migrations so schema changes are reviewable, reversible, and deployable.

Common Mistakes

  • Enabling synchronize: true in production environments.
  • Forgetting forFeature([Entity]) and getting Repository not found DI errors.
  • Using findOne without a where clause (deprecated / ambiguous in modern TypeORM).
  • Loading every relation with eager: true and creating unexpected query volume.

Key Takeaways

  • @nestjs/typeorm integrates TypeORM connection and repositories into Nest DI.
  • Entities map classes to tables; repositories provide typed CRUD helpers.
  • Register entities with forFeature in the module that needs them.
  • Prefer migrations over schema auto-sync for real environments.

Pro Tip

Create a thin custom repository provider around often-used queries (find by email, with relations) so services stay readable and your TypeORM specifics stay in one place.