Back to Articles

Meningkatkan Performa Sistem dengan CQRS

Pembahasan praktis tentang CQRS untuk meningkatkan performa sistem backend, memisahkan proses baca dan tulis, mempercepat dashboard, serta menjaga aplikasi tetap mudah dikembangkan.

Pada sistem yang mulai ramai digunakan, masalah performa sering muncul bukan karena server terlalu kecil, tetapi karena desain alur data belum dipisahkan dengan baik. Satu model yang sama dipakai untuk menulis data, membaca laporan, menampilkan dashboard, menjalankan filter, dan melayani API publik.

Awalnya pendekatan ini terasa sederhana. Tetapi ketika data bertambah, query makin kompleks, dan kebutuhan laporan makin banyak, sistem mulai terasa lambat. Dashboard butuh waktu lama untuk terbuka, endpoint API menjadi berat, dan perubahan kecil pada satu fitur bisa berdampak ke bagian lain.

Salah satu pola arsitektur yang bisa membantu adalah CQRS atau Command Query Responsibility Segregation.

Apa Itu CQRS?

CQRS adalah pola desain yang memisahkan tanggung jawab antara proses menulis data dan proses membaca data.

Dalam pendekatan biasa, satu model sering dipakai untuk dua hal sekaligus:

  • menyimpan atau mengubah data;
  • membaca data untuk halaman, laporan, dashboard, dan API.

Pada CQRS, dua kebutuhan itu dipisahkan:

  • Command side menangani perubahan data seperti membuat, mengubah, menyetujui, membatalkan, atau menghapus.
  • Query side menangani pembacaan data seperti daftar, detail, statistik, pencarian, laporan, dan dashboard.

Tujuannya bukan membuat sistem terlihat lebih rumit, tetapi membuat setiap sisi bisa dioptimalkan sesuai kebutuhannya.

Kenapa CQRS Bisa Meningkatkan Performa?

Masalah performa pada aplikasi bisnis biasanya banyak terjadi di sisi baca. Contohnya dashboard admin yang harus menampilkan total transaksi, status pembayaran, jumlah pengguna, laporan bulanan, dan data terbaru dalam satu halaman.

Jika semua data dihitung langsung dari tabel utama setiap kali halaman dibuka, query bisa menjadi berat. Apalagi jika tabel utama juga sedang dipakai untuk transaksi tulis.

Dengan CQRS, sistem bisa membuat model baca yang lebih ringan, misalnya:

  • tabel ringkasan transaksi harian;
  • materialized view untuk laporan;
  • cache statistik dashboard;
  • index khusus untuk pencarian;
  • read model khusus untuk halaman admin.

Command side tetap fokus menjaga validasi dan konsistensi data. Query side fokus menyajikan data secepat mungkin.

Contoh Masalah pada Sistem Tanpa CQRS

Bayangkan sebuah sistem pembayaran kampus. Sistem ini memiliki data mahasiswa, tagihan, pembayaran, metode pembayaran, status transaksi, dan riwayat perubahan.

Admin membutuhkan dashboard seperti:

  • total pembayaran hari ini;
  • jumlah transaksi pending;
  • jumlah pembayaran berhasil;
  • pembayaran berdasarkan fakultas atau program studi;
  • laporan transaksi per bulan;
  • pencarian invoice dan nama mahasiswa.

Jika dashboard langsung mengambil semua data dari tabel transaksi utama, query bisa menjadi berat. Tabel transaksi harus melayani dua beban sekaligus: proses pembayaran baru dan proses laporan.

Dalam jangka panjang, ini membuat sistem sulit berkembang. Setiap kebutuhan laporan baru menambah query kompleks pada database utama.

Cara CQRS Menyelesaikan Masalah Ini

Dengan CQRS, proses tulis dan baca dibuat lebih jelas.

Saat ada pembayaran masuk, command side menjalankan proses utama:

CreatePaymentCommand
ConfirmPaymentCommand
ExpirePaymentCommand
CancelPaymentCommand

Command side bertanggung jawab memastikan aturan bisnis terpenuhi, misalnya nominal harus benar, invoice belum expired, status tidak boleh mundur dari PAID ke PENDING, dan event pembayaran tidak boleh diproses dua kali.

Setelah command berhasil, sistem mengirim event seperti:

PaymentCreated
PaymentConfirmed
PaymentExpired
PaymentCancelled

Event ini kemudian dipakai untuk memperbarui query side. Query side dapat menyimpan data dalam bentuk yang lebih siap dibaca, misalnya tabel payment_dashboard_summary, payment_report_daily, atau student_invoice_search.

Ketika admin membuka dashboard, sistem tidak perlu menghitung ulang semuanya dari nol. Dashboard cukup membaca dari read model yang sudah disiapkan.

Struktur Sederhana CQRS

Secara sederhana, arsitektur CQRS bisa digambarkan seperti ini:

User / Admin

Command API ──→ Database utama

Domain Event

Projection / Worker

Read Model ──→ Query API ──→ Dashboard / Report

Bagian command API fokus pada perubahan data. Bagian query API fokus pada pembacaan data. Projection atau worker bertugas mengubah event menjadi data baca yang lebih efisien.

Pola ini bisa diterapkan secara sederhana di satu aplikasi monolith, atau dikembangkan lebih jauh pada microservices.

CQRS Tidak Harus Langsung Kompleks

Kesalahan umum saat membahas CQRS adalah menganggap pola ini harus selalu memakai event sourcing, message broker, microservices, dan banyak service terpisah. Padahal tidak selalu begitu.

Untuk banyak aplikasi, CQRS bisa dimulai dari level yang sederhana:

  • pisahkan service untuk command dan query;
  • gunakan DTO berbeda untuk request tulis dan response baca;
  • buat tabel ringkasan untuk dashboard;
  • gunakan job queue untuk memperbarui read model;
  • tambahkan cache untuk statistik yang sering dibaca.

Dengan pendekatan ini, sistem tetap mudah dipahami tetapi sudah mendapatkan manfaat pemisahan tanggung jawab.

Kapan CQRS Cocok Digunakan?

CQRS cocok digunakan ketika aplikasi memiliki ciri seperti ini:

  • data sering dibaca jauh lebih banyak daripada ditulis;
  • dashboard dan laporan mulai lambat;
  • query baca semakin kompleks;
  • kebutuhan tampilan data berbeda jauh dari struktur tabel utama;
  • sistem membutuhkan audit trail atau event historis;
  • fitur bisnis makin banyak dan validasi tulis makin rumit.

Contoh sistem yang cocok memakai CQRS:

  • sistem pembayaran kampus;
  • aplikasi ujian online dengan laporan nilai;
  • dashboard monitoring operasional;
  • sistem informasi akademik;
  • sistem arsip dan disposisi;
  • platform edukasi;
  • marketplace atau katalog transaksi;
  • sistem internal instansi.

Kapan CQRS Tidak Perlu Digunakan?

CQRS tidak selalu dibutuhkan. Untuk aplikasi kecil dengan CRUD sederhana, pola ini bisa menambah pekerjaan tanpa manfaat besar.

Jika aplikasi hanya memiliki sedikit data, sedikit pengguna, dan query yang masih sederhana, gunakan arsitektur biasa terlebih dahulu. Fokus pada struktur database yang rapi, index yang tepat, pagination, dan query yang efisien.

CQRS mulai layak dipertimbangkan ketika bottleneck sudah jelas: proses baca dan tulis punya kebutuhan yang berbeda, dan satu model mulai terlalu berat untuk melayani semuanya.

Implementasi dengan Laravel atau Spring Boot

Di Laravel, CQRS bisa dimulai dengan memisahkan class untuk command handler dan query handler. Command handler menangani proses seperti membuat transaksi, menyetujui data, atau mengubah status. Query handler menangani daftar, detail, filter, statistik, dan laporan.

Di Spring Boot, pola ini bisa dibuat lebih eksplisit dengan package terpisah, misalnya:

payment/
  command/
    CreatePaymentCommand.java
    ConfirmPaymentCommand.java
    PaymentCommandHandler.java
  query/
    PaymentDashboardQuery.java
    PaymentReportQuery.java
    PaymentQueryController.java
  projection/
    PaymentDashboardProjection.java

Struktur seperti ini membantu tim memahami bagian mana yang mengubah state dan bagian mana yang hanya membaca data.

Hal yang Perlu Dijaga

Menerapkan CQRS juga punya konsekuensi. Karena read model bisa diperbarui secara asynchronous, data pada dashboard mungkin tidak selalu real-time dalam hitungan milidetik. Ini disebut eventual consistency.

Untuk banyak kebutuhan bisnis, eventual consistency masih aman. Misalnya dashboard laporan terlambat satu atau dua detik biasanya tidak masalah, selama status transaksi utama tetap benar.

Beberapa hal yang perlu dijaga:

  • pastikan command side tetap menjadi sumber kebenaran utama;
  • simpan event penting untuk audit;
  • buat mekanisme retry jika projection gagal;
  • pantau job queue dan worker;
  • berikan timestamp lastUpdatedAt pada dashboard;
  • hindari duplikasi aturan bisnis di query side.

Penutup

CQRS membantu sistem backend tumbuh lebih sehat ketika kebutuhan baca dan tulis mulai berbeda. Dengan memisahkan command dan query, aplikasi bisa lebih mudah dioptimalkan, dashboard lebih cepat, laporan lebih ringan, dan aturan bisnis tetap terjaga di tempat yang tepat.

Untuk sistem seperti pembayaran kampus, dashboard admin, aplikasi ujian online, sistem informasi akademik, atau platform internal, CQRS bisa menjadi fondasi penting agar performa tetap stabil ketika data dan pengguna bertambah.

Kuncinya adalah mulai dari kebutuhan nyata. Jangan memakai CQRS hanya karena terdengar keren. Gunakan ketika sistem memang membutuhkan pemisahan alur tulis dan baca agar performa, maintainability, dan skalabilitas lebih terkontrol.

Diskusi proyek? Chat via WhatsApp