23 poin oleh GN⁺ 2026-01-23 | 4 komentar | Bagikan ke WhatsApp
  • soft delete berbasis kolom archived_at sering digunakan untuk pemulihan data dan kepatuhan regulasi, tetapi seiring waktu kompleksitas dan inefisiensi meningkat
  • Pendekatan ini membuat query, indeks, migrasi, dan logika pemulihan menjadi lebih rumit, dan karena sebagian besar data arsip tidak pernah dibaca lagi, hal ini menimbulkan beban yang tidak perlu pada database
  • Sebagai alternatif, diajukan arsip berbasis event aplikasi, arsip berbasis trigger, dan arsip berbasis WAL (Change Data Capture)
  • Setiap pendekatan berbeda dalam kompleksitas operasional, kebutuhan infrastruktur, dan kemudahan pemulihan, dan khususnya pendekatan berbasis WAL memerlukan integrasi dengan sistem eksternal seperti Kafka
  • Untuk proyek baru, pendekatan berbasis trigger adalah pilihan paling seimbang dari sisi kesederhanaan dan kemudahan pemeliharaan

Masalah pada soft delete

  • Umumnya data dihapus secara logis menggunakan kolom boolean deleted atau timestamp archived_at
    • Data bisa dipulihkan jika pelanggan tidak sengaja menghapusnya
    • Dalam beberapa kasus, data juga perlu disimpan untuk tujuan regulasi atau audit
  • Namun, kolom archived_at menimbulkan kompleksitas di seluruh query, operasi, dan kode aplikasi
    • Sebagian besar data arsip tidak pernah dibaca lagi
    • Karena masalah perilaku API atau alat otomasi seperti Terraform, jutaan baris yang tidak perlu bisa menumpuk
  • Jika pekerjaan pembersihan data arsip tidak dikonfigurasi, akan terjadi penurunan performa saat backup dan restore database
  • Data arsip harus difilter dalam query dan indeks, sehingga ada risiko kebocoran data
  • Saat migrasi, menangani data lama atau mengubah nilai default menjadi sulit
  • Logika pemulihan menjadi rumit, dan bug bisa muncul jika diperlukan pemanggilan sistem eksternal
  • Akibatnya, pendekatan archived_at tampak sederhana, tetapi dalam jangka panjang biaya pemeliharaannya tinggi

Arsip di level aplikasi

  • Saat penghapusan, aplikasi menerbitkan event, mengirimkannya ke SQS, lalu layanan lain mengarsipkannya ke S3
  • Kelebihan
    • Menyederhanakan database utama dan kode aplikasi
    • Pembersihan resource eksternal dapat diproses secara asinkron, meningkatkan performa dan keandalan
    • Dapat diserialisasi dalam bentuk JSON sehingga tersimpan dalam struktur yang ramah aplikasi
  • Kekurangan
    • Bug pada kode aplikasi dapat menyebabkan hilangnya data arsip
    • Kompleksitas infrastruktur operasional meningkat karena message queue dan komponen lain
    • Data arsip di S3 memerlukan alat pencarian dan pemulihan

Arsip berbasis trigger

  • Trigger sebelum penghapusan menyalin baris ke tabel archive terpisah dalam bentuk JSON
    • Contoh tabel: archive(id, table_name, record_id, data, archived_at, caused_by_table, caused_by_id)
  • Saat foreign key delete (cascade), digunakan variabel sesi (archive.cause_table, archive.cause_id) untuk melacak penyebab penghapusan
    • Memungkinkan penelusuran record induk mana yang menghapus data turunan
  • Kelebihan
    • Tabel live tetap bersih, tanpa perlu kolom archived_at
    • Pembersihan tabel arsip (WHERE archived_at < NOW() - INTERVAL '90 days') sederhana
    • Efisiensi query dan indeks tetap terjaga, migrasi lebih sederhana
    • Ukuran backup berkurang
  • Tabel arsip dapat dikelola dengan tablespace terpisah atau partisi berbasis waktu

Arsip berbasis WAL (Change Data Capture)

  • Log WAL PostgreSQL dibaca untuk men-stream event penghapusan ke sistem eksternal
    • Alat yang umum: Debezium (terintegrasi dengan Kafka)
    • Contoh alur: PostgreSQL → Debezium → Kafka → Consumer → Archive Storage
  • Alternatif yang lebih ringan
    • pgstream: mengirim WAL langsung ke webhook atau message queue
    • wal2json: mengeluarkan WAL dalam format JSON
    • pg_recvlogical: alat logical replication bawaan PostgreSQL
  • Kompleksitas operasional
    • Pendekatan berbasis Kafka memerlukan monitoring, penanganan gangguan, dan tuning
    • Jika consumer tertunda, dapat terjadi penumpukan file WAL → risiko kehabisan ruang disk
    • Ini dapat dibatasi dengan pengaturan max_slot_wal_keep_size pada PostgreSQL 13+
    • Monitoring dan alert untuk keterlambatan replication slot wajib ada
  • Kelebihan
    • Dapat menangkap semua perubahan tanpa memodifikasi kode aplikasi
    • Dapat di-stream ke berbagai tujuan (S3, data warehouse, indeks pencarian)
    • Tidak menambah beban pada database utama
  • Kekurangan
    • Kompleksitas operasional dan biaya infrastruktur tinggi
    • Jika consumer tertunda, bisa terjadi kehilangan data atau perlu sinkronisasi ulang
    • Saat skema berubah, diperlukan koordinasi antara source dan consumer

Ide replika yang tidak memproses penghapusan

  • Diajukan ide untuk mempertahankan replika PostgreSQL yang mengabaikan query DELETE
    • Semua data yang tidak dihapus dapat terus diakumulasikan sebagai arsip
    • Data arsip bisa di-query langsung
  • Potensi masalah
    • Mungkin sulit membedakan informasi penghapusan
    • Ada risiko konflik saat migrasi diterapkan
    • Biaya penyimpanan dan operasional meningkat

Kesimpulan

  • Untuk proyek baru, arsip berbasis trigger adalah pilihan yang paling praktis
    • Konfigurasinya sederhana dan menjaga tabel live tetap bersih
    • Tanpa infrastruktur tambahan, data arsip tetap mudah diakses dan dikelola
  • Jika infrastruktur kompleks sudah tersedia atau diperlukan streaming ke banyak tujuan, maka pendekatan berbasis WAL lebih cocok

4 komentar

 
love7peace 2026-01-23

Kalau berbasis trigger, bukannya saya belajar itu akan membebani DB...? Malah merekomendasikan trigger ya

 
nemorize 2026-01-24

Jika beban yang muncul dari trigger sebesar itu saja sudah jadi masalah, maka bahkan tanpa trigger pun situasinya memang sudah penuh masalah.

 
cherrycoder 2026-01-23

Pada akhirnya, regulasi itu memang selalu menimbulkan biaya. Yah, bagaimanapun juga itu adalah bagian yang harus ditanggung konsumen.

 
GN⁺ 2026-01-23
Komentar Hacker News
  • Di domain perbankan tempat saya bekerja, saya justru merasa soft delete lebih menguntungkan
    Jika ada kolom deleted_at, penulisan kueri jadi jelas, dan kueri analitik maupun halaman admin bisa menangani dataset yang sama
    Penghapusan dalam banyak kasus jarang terjadi, dan baris yang di-soft delete juga hampir tidak pernah menimbulkan masalah performa
    Selain itu, karena relasi tetap terjaga, pemulihan (undo) juga sederhana
    Saya bahkan lebih suka membuat baris benar-benar immutable dan menambahkan baris baru saat update
    Untuk meninggalkan log, saya rasa pendekatan yang baik adalah memakai trigger DB agar saat INSERT/UPDATE/DELETE terjadi, catatan ditulis ke tabel salinan

    • Kamu benar, tapi menurut saya itu hanya berlaku jika penghapusan memang jarang terjadi
      Pada tabel yang pernah saya lihat, ketika 50~70% isinya sudah di-soft delete, penurunan performa memang jelas terlihat
      Pada akhirnya soft delete bergantung pada konteks, dan perlu analisis awal
    • Di Postgres, kita juga bisa mengatur agar hanya data yang belum di-soft delete yang diindeks
      Dalam kebanyakan kasus ini tidak perlu, tapi bisa membantu menghemat RAM
    • Di bank, soft delete hanyalah solusi sementara yang menutupi kurangnya auditability
      Solusi yang sebenarnya adalah Event Sourcing, yaitu mencatat semua perubahan sebagai event
      Performanya memang lebih rendah, tapi bisa ditutupi dengan snapshot dan sinkronisasi (sync)
    • Jika ingin mengoperasikan DB dengan struktur immutable, sistem seperti Datomic layak dipertimbangkan
      Dengan fitur time travel, status masa lalu bisa ditelusuri secara utuh
    • Saat dulu bekerja di perusahaan asuransi, tiap tabel juga dijalankan sebagai log append-only
      Status terbaru ada di baris dengan timestamp terbesar, dan status masa lalu bisa dilihat lewat filter
      Pendekatan ini memungkinkan pengelolaan riwayat yang kuat
  • Jebakan terbesar soft delete adalah kompleksitas kueri
    Awalnya terasa cukup dengan menambahkan WHERE deleted_at IS NULL, tapi beberapa bulan kemudian data hantu muncul di laporan karena filter terlewat
    Ini bisa diatasi dengan View, tetapi pada akhirnya kita tetap harus mempertahankan pola akses paralel, dan saat perlu melihat data yang sudah dihapus, abstraksinya harus dilewati
    Event sourcing lebih bersih, tetapi karena beban operasional-nya besar, kebanyakan orang memilih pendekatan hibrida

    • View adalah alat yang cukup kuat
      Masalahnya, banyak SWE dan engineer BI tidak terbiasa dengan SQL dan desain skema
      Masalah yang bahkan lebih umum daripada soft delete adalah penanganan Type 2 Slowly Changing Dimension
      Kebanyakan orang membuat audit table yang sebenarnya tidak perlu, lalu mengulang UPDATE/INSERT yang tidak efisien
      Padahal DB itu sistem yang sangat indah, dan sayangnya tidak cukup dihargai
  • Saya pikir akan bagus jika soft delete tersedia sebagai fitur bawaan DB
    Akan ideal jika bisa diaktifkan per tabel dan strategi penanganan penghapusannya dapat dipilih

    • Faktanya, sistem seperti Iceberg, Delta Lake, BigQuery memang menyediakan fitur time travel
      Namun banyak tim akhirnya tetap mengimplementasikannya dengan pendekatan SCD (Slowly Changing Dimension) karena kebutuhan khusus
  • Dalam pengalaman saya, pendekatan berbasis trigger adalah yang paling stabil
    Tabel arsip sebaiknya dipertahankan sebagai append-only, dan pemulihan ditangani di layer aplikasi
    Update diperlakukan sebagai soft delete, dan trigger menangkap status sebelumnya
    Trigger harus dijalankan pada tahap BEFORE, dan logikanya harus sederhana
    Partisi bulanan adalah yang umum, dan jika beban tulis tinggi, lebih baik dibagi harian

  • Saya ingin DB berevolusi dari stateful → stateless
    Saya lebih suka struktur yang mencatat semua perubahan sebagai event append-only, lalu mengekspresikan data yang dibutuhkan lewat view
    Akan ideal jika DB otomatis mengelola materialized index
    Beberapa DB modern memang menyediakan fitur seperti ini, tetapi perkembangan yang berfokus pada OLTP masih kurang

    • Ini pada akhirnya adalah konsep Event Sourcing
      Penjelasan Martin Fowler layak dijadikan referensi
  • Di perusahaan lama saya, soft delete diterapkan di semua sistem
    Saya masih ingat profesor saya pernah berkata, “di dunia bisnis, data tidak pernah benar-benar dihapus

    • Menghapus permanen pada dasarnya membatasi sendiri kemampuan analisis data di masa depan
      Ruang penyimpanan itu murah, jadi data seharusnya jangan pernah dihapus
    • Tapi menarik juga bahwa profesor itu tidak mengatakan apa pun soal modifikasi data
  • Database adalah tempat menyimpan fakta (fact)
    Pembuatan record adalah fakta baru, penghapusan juga fakta lain
    Tetapi jika baris dihapus secara fisik, maka fakta itu hilang
    Dalam banyak kasus, penghapusan seperti ini tidak diinginkan

    • Namun jika data adalah aset yang punya risiko kebocoran, justru penghapusan massal mungkin diperlukan
      Biaya retensi dan risiko keamanan harus dipertimbangkan
    • Jika DB tidak immutable, maka modifikasi itu sendiri sudah menciptakan fakta yang hilang
      Keputusan untuk menyimpan data secara permanen harus dipikirkan dengan matang
    • Secara pribadi saya merasa penyimpanan data seharusnya hanya mendukung dua operasi: query dan insert
      Untuk itu, memahami siklus hidup data adalah hal yang penting
  • Di Firezone, awalnya soft delete dipakai untuk audit log, tetapi akhirnya ditinggalkan karena masalah migrasi
    Sebagai gantinya, mereka beralih memakai Postgres CDC (Change Data Capture) untuk mengekspor event ke tabel terpisah yang dioptimalkan untuk penulisan
    Menurut saya soft delete berguna untuk fitur pemulihan pengguna, tetapi tidak cocok untuk audit atau kepatuhan

    • Untuk proyek sederhana, daripada mengaudit perubahan DB, sering kali lebih efisien mengaudit pemanggilan API itu sendiri
  • Membuat View di atas tabel yang punya field soft delete untuk menyembunyikan baris yang sudah dihapus adalah pendekatan yang rapi
    Dengan begitu aplikasi tidak perlu peduli apakah data sudah dihapus atau belum

    • Dengan memanfaatkan RLS (Row Level Security) di Postgres, baris yang di-soft delete bisa disembunyikan secara otomatis
      Aplikasi tetap melakukan baca/tulis/hapus ke tabel yang sama
  • Ada pertanyaan tentang bagaimana menangani schema drift
    Jika ingin memulihkan data yang diserialisasi dengan skema saat data itu dihapus, perubahan skema akan menjadi masalah

    • Dalam pengalaman saya, objek yang diarsipkan hampir tidak pernah diakses
      Kebanyakan pemulihan terjadi hanya dalam beberapa hari setelah penghapusan, jadi dampak perubahan skema kecil
      Memigrasikan arsip lama ke model baru adalah pekerjaan yang rumit dan rawan kesalahan
      Pada akhirnya strategi pendekatannya berbeda tergantung bagaimana sistem itu digunakan