Episode ini memperdalam persistence: manajemen transaksi dengan database adapter, unit of work dan repository orchestration, optimasi query dengan eager dan lazy loading, serta connection pooling untuk performance tuning.

Operasi database yang melibatkan beberapa langkah harus konsisten — jika satu langkah gagal, semua harus dibatalkan. Di sinilah transaksi berperan. Episode 10 membahas transaksi di TypeORM, unit of work, optimasi query, dan connection pooling.
Konsep ini penting untuk aplikasi yang memproses uang, stok, atau data yang membutuhkan konsistensi ketat.
Bayangkan transfer uang: saldo pengirim dikurangi dan saldo penerima ditambah. Jika langkah kedua gagal, saldo pengirim berkurang tanpa diterima siapa pun. Transaksi memastikan kedua operasi berhasil bersama-sama atau gagal bersama-sama.
TypeORM menyediakan API transaksi lewat DataSource:
import { Injectable } from "@nestjs/common";
import { InjectDataSource } from "@nestjs/typeorm";
import { DataSource } from "typeorm";
@Injectable()
export class TransferService {
constructor(
@InjectDataSource()
private readonly dataSource: DataSource,
) {}
async transfer(fromId: number, toId: number, amount: number): Promise<void> {
await this.dataSource.transaction(async (manager) => {
const from = await manager.findOneBy(User, { id: fromId });
const to = await manager.findOneBy(User, { id: toId });
from.balance -= amount;
to.balance += amount;
await manager.save([from, to]);
});
}
}Callback yang menerima manager menjalankan semua operasi dalam satu transaksi. Jika ada exception, transaksi otomatis di-rollback.
Unit of Work mengelompokkan beberapa operasi menjadi satu unit logis. EntityManager dari TypeORM adalah implementasi unit of work — semua perubahan dalam transaksi di-manage oleh satu manager.
async createOrder(orderData: OrderDto): Promise<void> {
await this.dataSource.transaction(async (manager) => {
const order = manager.create(Order, orderData);
await manager.save(order);
for (const item of orderData.items) {
await manager.decrement(Product, { id: item.productId }, "stock", item.qty);
}
});
}Dalam satu transaksi, service mengoordinasikan pembuatan order sekaligus pengurangan stok — contoh orchestration antar repository.
Relasi bisa dimuat bersamaan dengan entity utama memakai relations:
async findOrdersWithUser(): Promise<Order[]> {
return this.ordersRepository.find({
relations: {
user: true,
items: true,
},
});
}Memuat user dan items sekaligus menghindari masalah N+1 — banyak query kecil yang memperlambat aplikasi.
Alternatifnya, relasi lazy dimuat hanya saat diakses:
@Entity()
export class Order {
@ManyToOne(() => User)
user: Promise<User>;
}Dengan Promise<User>, relasi dimuat saat di-await. Berhati-hatilah dengan lazy loading karena bisa memicu query yang tak terduga di dalam loop.
Selalu tambahkan index untuk kolom yang sering difilter:
@Entity()
export class User {
@Column()
name: string;
@Index()
@Column({ unique: true })
email: string;
}Index mempercepat pencarian berdasarkan email secara signifikan, terutama pada tabel besar.
Connection pool menjaga sekumpulan koneksi database yang dipakai ulang, mengurangi overhead membuat koneksi baru setiap request:
TypeOrmModule.forRoot({
type: "postgres",
url: process.env.DATABASE_URL,
autoLoadEntities: true,
synchronize: false,
poolSize: 10,
})poolSize: 10 membatasi jumlah koneksi bersamaan. Atur sesuai beban dan kemampuan database.
Beberapa praktik tuning: matikan synchronize di production, batasi hasil dengan take dan skip, hindari select * yang tidak perlu, dan gunakan query builder untuk query kompleks. Kombinasi ini menjaga aplikasi tetap responsif seiring data bertambah.
Episode 10 memperkuat kemampuan persistence kalian: transaksi untuk konsistensi, unit of work untuk orchestration, optimasi query untuk kecepatan, dan connection pooling untuk skalabilitas.
Inti yang harus dibawa pulang:
dataSource.transaction menerima callback dengan manager.Di episode 11 selanjutnya kita akan membahas background jobs dan scheduling — task scheduling dengan @nestjs/schedule, queue processing dengan Bull atau BullMQ, retry policy dan delayed jobs, serta monitoring job dan failure handling.