Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
40 prioritized NestJS best practices across architecture, DI, security, performance, testing, and microservices.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
rules/db-use-transactions.md
1---2title: Use Transactions for Multi-Step Operations3impact: HIGH4impactDescription: Ensures data consistency in multi-step operations5tags: database, transactions, typeorm, consistency6---78## Use Transactions for Multi-Step Operations910When multiple database operations must succeed or fail together, wrap them in a transaction. This prevents partial updates that leave your data in an inconsistent state. Use TypeORM's transaction APIs or the DataSource query runner for complex scenarios.1112**Incorrect (multiple saves without transaction):**1314```typescript15// Multiple saves without transaction16@Injectable()17export class OrdersService {18async createOrder(userId: string, items: OrderItem[]): Promise<Order> {19// If any step fails, data is inconsistent20const order = await this.orderRepo.save({ userId, status: 'pending' });2122for (const item of items) {23await this.orderItemRepo.save({ orderId: order.id, ...item });24await this.inventoryRepo.decrement({ productId: item.productId }, 'stock', item.quantity);25}2627await this.paymentService.charge(order.id);28// If payment fails, order and inventory are already modified!2930return order;31}32}33```3435**Correct (use DataSource.transaction for automatic rollback):**3637```typescript38// Use DataSource.transaction() for automatic rollback39@Injectable()40export class OrdersService {41constructor(private dataSource: DataSource) {}4243async createOrder(userId: string, items: OrderItem[]): Promise<Order> {44return this.dataSource.transaction(async (manager) => {45// All operations use the same transactional manager46const order = await manager.save(Order, { userId, status: 'pending' });4748for (const item of items) {49await manager.save(OrderItem, { orderId: order.id, ...item });50await manager.decrement(51Inventory,52{ productId: item.productId },53'stock',54item.quantity,55);56}5758// If this throws, everything rolls back59await this.paymentService.chargeWithManager(manager, order.id);6061return order;62});63}64}6566// QueryRunner for manual transaction control67@Injectable()68export class TransferService {69constructor(private dataSource: DataSource) {}7071async transfer(fromId: string, toId: string, amount: number): Promise<void> {72const queryRunner = this.dataSource.createQueryRunner();73await queryRunner.connect();74await queryRunner.startTransaction();7576try {77// Debit source account78await queryRunner.manager.decrement(79Account,80{ id: fromId },81'balance',82amount,83);8485// Verify sufficient funds86const source = await queryRunner.manager.findOne(Account, {87where: { id: fromId },88});89if (source.balance < 0) {90throw new BadRequestException('Insufficient funds');91}9293// Credit destination account94await queryRunner.manager.increment(95Account,96{ id: toId },97'balance',98amount,99);100101// Log the transaction102await queryRunner.manager.save(TransactionLog, {103fromId,104toId,105amount,106timestamp: new Date(),107});108109await queryRunner.commitTransaction();110} catch (error) {111await queryRunner.rollbackTransaction();112throw error;113} finally {114await queryRunner.release();115}116}117}118119// Repository method with transaction support120@Injectable()121export class UsersRepository {122constructor(123@InjectRepository(User) private repo: Repository<User>,124private dataSource: DataSource,125) {}126127async createWithProfile(128userData: CreateUserDto,129profileData: CreateProfileDto,130): Promise<User> {131return this.dataSource.transaction(async (manager) => {132const user = await manager.save(User, userData);133await manager.save(Profile, { ...profileData, userId: user.id });134return user;135});136}137}138```139140Reference: [TypeORM Transactions](https://typeorm.io/transactions)141