CodePark/ questions / Database integration (TypeORM / Prisma)
START PRACTICINGPRACTICE
Backend question · NestJS › Database integration (TypeORM / Prisma)

How do you run several TypeORM operations in one transaction inside a Nest service?

@Injectable()
export class TransfersService {
  constructor(private dataSource: DataSource) {}

  transfer(fromId: number, toId: number, amount: number) {
    return this.dataSource.transaction(async (manager) => {
      await manager.decrement(Account, { id: fromId }, "balance", amount);
      await manager.increment(Account, { id: toId }, "balance", amount);
    });
  }
}

Inject the DataSource and call dataSource.transaction(async (manager) => ...). This works once TypeOrmModule is set up.

The transaction method opens a transaction. It commits when the callback finishes successfully. It rolls back if the callback throws.

Every query inside must use the manager that the callback receives. Don't use an injected repository there. Injected repositories run outside the transaction, so their changes are not rolled back.

For more control, use a QueryRunner:

  • Create it with dataSource.createQueryRunner().
  • Call connect() and startTransaction().
  • In a try/catch, call commitTransaction() on success or rollbackTransaction() on error.
  • Always call release() in finally, so the connection goes back to the pool.

The Nest docs suggest putting this logic in its own class. Then the transaction logic is easy to mock in unit tests.

  • Inject the DataSource.
  • dataSource.transaction(cb) commits on success and rolls back on error.
  • Use the callback's manager, not injected repositories.
  • Use a QueryRunner for manual control, and always call release().