Melindungi data pengguna sesuai regulasi: memahami GDPR dan prinsip data minimization, mengenkripsi data saat transit dan saat istirahat, logging yang aman, serta menyusun checklist compliance yang bisa diaudit

Episode 17-18 mengamankan sistem dari serangan. Episode 19 membahas lapisan berikutnya: melindungi hak pengguna atas data mereka — bukan karena diserang, tapi karena diwajibkan hukum. Regulasi seperti GDPR (Uni Eropa) dan UU Perlindungan Data Pribadi di banyak negara mengubah cara backend menangani data pribadi.
Mengapa backend developer harus paham compliance? Karena sanksinya nyata — GDPR mengenakan denda hingga 4% dari omset global — dan karena aturan ini memengaruhi keputusan teknis harian: di mana data disimpan, bagaimana dienkripsi, apa yang boleh di-log, dan bagaimana data dihapus saat user meminta. Episode ini membangun prinsip dan praktik compliance data.
Prinsip pertama GDPR dan regulasi serupa: jangan kumpulkan data yang tidak dibutuhkan. Semakin sedikit data pribadi yang kalian simpan, semakin kecil risiko dan kewajiban.
| Pertanyaan desain | Contoh yang baik | Contoh yang buruk |
|---|---|---|
| Field apa yang wajib di form? | Nama + email | Nama, email, tanggal lahir, alamat, agama |
| Apakah perlu tanggal lahir? | Hanya jika ada syarat umur | "Untuk profil" (tidak dipakai) |
| Berapa lama data disimpan? | Hapus akun uji 30 hari | Simpan selamanya |
| Apakah log menyimpan body? | Log hanya status & id | Log body penuh (mengandung data pribadi) |
Terapkan data minimization sejak desain skema (episode 5): setiap kolom harus punya alasan bisnis.
Data bergerak di jaringan — dari user ke server, dari server ke database. Data yang tidak dienkripsi saat transit bisa disadap (man-in-the-middle).
Semua traffic HTTP di produksi wajib lewat HTTPS/TLS:
https saja yang dipakai untuk integrasi pihak ketiga — http untuk API internal pun sebaiknya dihindari jika melewati jaringan bersama.Browser --TLS--> Load Balancer --TLS--> API --TLS--> DatabaseSatu kesalahan umum: database di-cloud dibuka ke IP publik tanpa TLS. Managed database (episode 16) menyediakan encrypted connection — aktifkan dan wajibkan sertifikat.
Note
Enkripsi saat transit mencegah penyadapan; tidak melindungi data di server. Jika database dicuri, data di dalamnya masih terbaca. Untuk itu ada enkripsi saat istirahat — lapisan berikutnya.
Data yang disimpan (at rest) harus dilindungi jika media penyimpanan jatuh ke tangan salah.
Semua cloud provider menyediakan volume encryption — hard disk yang dienkripsi. Ini lapisan dasar: aktifkan di semua volume dan database.
Untuk data yang paling sensitif — nomor kartu, data kesehatan, dokumen identitas — enkripsi di level aplikasi, sehingga database yang bocor tetap tidak bisa membaca datanya.
import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto"
const KEY = Buffer.from(process.env.DATA_ENCRYPTION_KEY!, "hex")
export function encryptField(plain: string): string {
const iv = randomBytes(16)
const cipher = createCipheriv("aes-256-gcm", KEY, iv)
const encrypted = Buffer.concat([cipher.update(plain, "utf8"), cipher.final()])
const tag = cipher.getAuthTag()
return [iv.toString("hex"), tag.toString("hex"), encrypted.toString("hex")].join(":")
}
export function decryptField(payload: string): string {
const [ivHex, tagHex, dataHex] = payload.split(":")
const decipher = createDecipheriv("aes-256-gcm", KEY, Buffer.from(ivHex, "hex"))
decipher.setAuthTag(Buffer.from(tagHex, "hex"))
return Buffer.concat([
decipher.update(Buffer.from(dataHex, "hex")),
decipher.final(),
]).toString("utf8")
}Kunci enkripsi (key management) adalah bagian tersulit: simpan di KMS (AWS/GCP/Azure Key Management Service), bukan di kode atau env biasa. KMS mengelola rotasi dan akses kunci.
Warning
Data yang dienkripsi dengan kunci yang ikut bocor (di kode, di config, di git) tidak terlindungi sama sekali. Kunci enkripsi wajib dipisah dari data — kelola di KMS atau Vault, dan rotasi secara berkala. Jangan pernah menaruh DATA_ENCRYPTION_KEY di repository (episode 17).
Log (episode 11) adalah jebakan data pribadi — email, token, body penuh sering ikut tercatat. Compliance mewajibkan log yang mematuhi privacy:
import pino from "pino"
export const logger = pino({
redact: {
paths: [
"req.headers.authorization",
"req.body.email",
"req.body.password",
"user.email",
],
censor: "[REDACTED]",
},
})redact mengganti nilai field sensitif dengan [REDACTED] — log tetap berguna untuk debugging tanpa menyimpan data pribadi. Kebijakan logging privacy-first:
GDPR memberi user hak atas data mereka — termasuk right to erasure ("right to be forgotten"). Backend harus bisa menghapus data user secara lengkap.
export async function deleteUserAccount(userId: number, tx) {
// hapus semua data turunan dalam satu transaction (episode 5)
await tx.query("DELETE FROM sessions WHERE user_id = $1", [userId])
await tx.query("DELETE FROM addresses WHERE user_id = $1", [userId])
await tx.query("DELETE FROM users WHERE id = $1", [userId])
}Pertanyaan desain yang harus dijawab: apakah data order dipertahankan setelah akun dihapus? GDPR mengizinkan menyimpan data yang wajib hukum (fiskal) — tetapi harus anonymized atau terpisah dari identitas user. Desain skema sejak awal dengan memikirkan deletion.
Compliance membutuhkan bukti — siapa mengakses/mengubah apa, kapan. Audit log berbeda dari log aplikasi biasa: ia tidak boleh berubah (immutable) dan tidak boleh dihapus oleh user.
| Event | Yang dicatat |
|---|---|
| Login/logout | userId, IP, waktu |
| Perubahan data sensitif | userId, field, nilai lama → baru |
| Delete akun | userId, waktu, alasan |
| Akses admin ke data | adminId, target, waktu |
Contoh bentuk audit trail:
{
"event": "user.deleted",
"actor": "admin@shop.example",
"target": "user:987",
"timestamp": "2026-08-16T10:00:00Z",
"reason": "GDPR erasure request"
}Simpan audit trail terpisah (tabel/append-only), dan buat tidak bisa diubah (misal di log immutable atau database append-only).
Jadikan checklist ini bagian dari definisi "selesai" setiap fitur:
Tip
Compliance dimulai dari mengetahui data apa yang kalian simpan. Buat peta data sederhana: kolom/tabel mana berisi data pribadi, di mana mengalir, dan berapa lama disimpan. Dari peta itu, semua keputusan — enkripsi, log, retention, deletion — jauh lebih mudah. Tidak ada alat compliance yang menggantikan pemahaman ini.
Data yang tersimpan tetap perlu perlindungan. Enkripsi transit dan at-rest saling melengkapi, bukan pengganti.
Enkripsi dengan kunci yang ikut bocor = kosmetik. Kelola kunci di KMS.
Log body penuh atau email = pelanggaran compliance tersembunyi. Redact dan minimization.
Menghapus user dari tabel users tapi data order/address/session tertinggal = erasure tidak lengkap. Petakan semua tabel turunan.
Episode 19 melindungi data pengguna: data minimization sebagai prinsip desain, enkripsi saat transit (TLS) dan saat istirahat (disk + kolom aplikasi), privacy-first logging, hak user atas penghapusan data, dan audit trail yang immutable.
Inti yang harus dibawa pulang:
Di episode 20 selanjutnya kita akan melindungi ketersediaan: rate limiting & DDoS protection — membatasi akses per endpoint dan mempertahankan layanan dari serangan banjir. Sampai jumpa di episode 20!