Data Lake Architecture — Data Engineering

Data Lake Architecture Data lake adalah sistem penyimpanan yang menyimpan data dalam format mentah (raw) dalam skala besar. Berbeda dengan data warehouse yang…

Data lake adalah tempat menyimpan data sebagai file di object storage (S3, GCS, Cloudflare R2, Azure Blob), dalam format apa pun dan dalam bentuk aslinya, supaya murah disimpan banyak dan bisa dibaca banyak mesin. Bayangin gudang ekspedisi. Paket masuk disimpan apa adanya di rak yang diberi label tanggal: murah, muat apa saja, dan gak perlu dibongkar dulu. Toko di depan (warehouse) cuma memajang barang yang sudah dirapikan dan diberi harga. Gudang yang raknya gak berlabel dan gak ada yang mencatat isinya lama-lama jadi tumpukan yang gak ada yang berani sentuh.

🧪 Tebakan cepat: penjualan bersih Toko Buku disimpan sebagai 11 file Parquet, satu folder per hari (dt=2026-09-28/ sampai dt=2026-10-09/). Query WHERE dt = '2026-10-01' membuat DuckDB membuka berapa file? Dan WHERE kota = 'Bandung'? Tebak dulu, jawabannya ada di bagian "Partisi: satu folder per hari".

Lake, warehouse, lakehouse

Data warehouse Data lake Lakehouse
Isinya tabel yang sudah bersih file apa saja: CSV, JSON, Parquet, log, gambar file Parquet + metadata tabel
Schema dicek saat data ditulis (schema-on-write) diterapkan saat data dibaca (schema-on-read) dicek saat ditulis, bisa berubah tercatat
Tempat BigQuery, Snowflake, Redshift, file DuckDB S3, GCS, R2 S3, GCS, R2
Dibaca dengan mesin warehouse itu DuckDB, Spark, Trino, pandas mesin mana pun yang paham format tabelnya

Perbedaan utamanya: lake menyimpan data mentah dalam format aslinya dan schema baru diterapkan waktu dibaca, warehouse menyimpan data terstruktur yang schema-nya dicek waktu masuk. Lakehouse menambahkan fitur warehouse (transaksi, perubahan schema, versi lama) di atas file lake.

Lapisan bronze, silver, gold

Lake biasanya dibagi tiga lapisan (medallion architecture). Ini lake Toko Buku dari satu run DuckDB 1.5.6 di laptop, dengan ukuran file aslinya:

lake/
├── bronze/order_lines/              mentah, CSV, persis seperti ekstrak
│   ├── dt=2026-09-28/data_0.csv     291 byte, 3 baris
│   ├── dt=2026-10-01/data_0.csv     274 byte, 3 baris (item 9 masih ada)
│   └── ... (11 folder, 28 September sampai 9 Oktober)
├── silver/penjualan/                bersih, Parquet
│   ├── dt=2026-09-28/data_0.parquet 1.137 byte, 3 baris
│   ├── dt=2026-10-01/data_0.parquet 1.083 byte, 2 baris
│   └── ... (11 folder juga)
└── gold/juara_mingguan.parquet      790 byte, jawaban pemilik (9 baris)

Partisi: satu folder per hari

Partisi artinya data dipecah ke folder menurut nilai satu kolom. Nama foldernya kolom=nilai (gaya Hive), jadi mesin query tahu isi folder tanpa membukanya. Script yang membangun lake di atas:

import os
import duckdb

for lapisan in ["bronze", "silver", "gold"]:
    os.makedirs(f"lake/{lapisan}", exist_ok=True)

con = duckdb.connect()

# Bronze: salinan mentah apa adanya, CSV, satu folder per hari
con.sql("""
COPY (SELECT *, CAST(created_at AS DATE) AS dt FROM 'order_lines.csv')
TO 'lake/bronze/order_lines' (FORMAT csv, HEADER, PARTITION_BY (dt), OVERWRITE)
""")

# Silver: sudah dibersihkan, Parquet, tetap satu folder per hari
con.sql("""
COPY (
  SELECT r.order_id, r.book_id, r.created_at,
         COALESCE(r.city, 'Tidak diketahui') AS kota,
         r.title AS judul, r.qty, b.catalog_price AS harga, r.dt
  FROM read_csv('lake/bronze/order_lines/*/*.csv', hive_partitioning = true) r
  JOIN 'books.csv' b ON b.book_id = r.book_id
  QUALIFY ROW_NUMBER() OVER (PARTITION BY r.order_id, r.book_id ORDER BY r.item_id) = 1
)
TO 'lake/silver/penjualan' (FORMAT parquet, PARTITION_BY (dt), OVERWRITE)
""")

# Gold: query juara per kota per minggu dari silver, COPY ke
# lake/gold/juara_mingguan.parquet (dipendekkan)

Lalu query ke silver dengan filter tanggal:

print(con.sql("""
SELECT dt, kota, judul, qty, harga
FROM read_parquet('lake/silver/penjualan/*/*.parquet', hive_partitioning = true)
WHERE dt = '2026-10-01'
"""))

Baris hasilnya, lalu potongan EXPLAIN ANALYZE untuk query yang sama:

│ 2026-10-01 │ Jakarta │ Bumi Manusia │     2 │ 125000 │
│ 2026-10-01 │ Bandung │ Bumi Manusia │     1 │ 125000 │

│       File Filters:       │
│ (dt = '2026-10-01'::DATE) │
│                           │
│    Scanning Files: 1/11   │
│    Total Files Read: 1    │

DuckDB membuka 1 dari 11 file; 10 folder lain dilewati hanya dari namanya. Itu jawaban tebakannya. WHERE dt >= '2026-10-05' membuka 5 dari 11. WHERE kota = 'Bandung' membuka 11 dari 11: kota bukan kolom partisi, jadi semua file harus dibaca dulu baru disaring (hasilnya 5 baris). Pilih kolom partisi dari filter yang paling sering dipakai, biasanya tanggal.

Open table format: Iceberg, Delta Lake, Hudi

Folder Parquet biasa gak punya transaksi. Kalau COPY ... OVERWRITE mati di tengah, sebagian folder sudah baru dan sebagian masih lama, dan query yang jalan saat itu membaca campurannya. Open table format menambahkan file metadata di samping file Parquet yang mencatat file mana saja yang menyusun versi tabel saat ini. Tiga yang dipakai luas (versi terbaru per Oktober 2026):

Format Versi Asal
Apache Iceberg 1.12.0 (30 September 2026) Netflix, sekarang proyek Apache
Delta Lake 4.4.1 (5 Oktober 2026) Databricks, sekarang Linux Foundation
Apache Hudi 1.2.1 (24 September 2026) Uber, sekarang proyek Apache

Yang ditambahkan ketiganya:

Untuk membaca dan menulisnya dipakai Spark, Flink, Trino, atau DuckDB (extension iceberg dan delta), plus sebuah catalog yang mencatat tabel apa saja yang ada dan di mana.

Kapan Toko Buku butuh semua ini

Jujur saja: sekarang belum. 19 baris pesanan muat di satu file DuckDB atau satu PostgreSQL replica, dan query-nya selesai dalam milidetik. Silver Toko Buku malah lebih besar dari sumbernya: 11 file Parquet masing-masing sekitar 1,1 KB, hampir 12 KB total, padahal order_lines.csv cuma 1.449 byte. Tiap file Parquet membawa schema dan metadatanya sendiri, dan untuk 1 sampai 3 baris per file, biaya itu yang dominan.

Lake mulai masuk akal kalau datanya sudah gigabyte sampai terabyte, datang dari banyak sumber (log klik, event aplikasi, file dari partner), ada data yang bukan tabel (gambar sampul, PDF), atau beberapa mesin dan tim harus membaca data yang sama. Lakehouse masuk akal kalau di atas itu kamu butuh update, delete, dan versi lama di lake.

⚠️ Jebakan yang sering ketemu

TL;DR: Data lake menyimpan data sebagai file di object storage, mentah dalam format aslinya, dengan schema yang diterapkan saat dibaca (schema-on-read); warehouse menyimpan tabel terstruktur yang dicek saat ditulis (schema-on-write); lakehouse menambahkan fitur warehouse di atas file lake. Lake dibagi bronze (mentah), silver (bersih), gold (siap pakai), dan dipartisi per folder dt=2026-10-01/: filter di kolom partisi membuat DuckDB membuka 1 dari 11 file, filter di kolom lain tetap membuka 11. Iceberg 1.12, Delta Lake 4.4, dan Hudi 1.2 menambahkan transaksi ACID, schema evolution, dan time travel. Lake tanpa catalog, pemilik, dan cek kualitas jadi data swamp. Untuk data sekecil Toko Buku, satu database sudah cukup; lake baru untung di gigabyte, banyak sumber, dan banyak pembaca.

Yang akan kamu pelajari