Tutorial

Arsitektur LTAP: Postgres + Parquet + S3 untuk Data Analytics Modern 2026

Arsitektur LTAP: Postgres + Parquet + S3 untuk Data Analytics Modern 2026

Selama hampir 15 tahun, arsitektur data umumnya terbagi dua: OLTP (Online Transactional Processing) untuk aplikasi production seperti Postgres atau MySQL, dan OLAP (Online Analytical Processing) untuk data warehouse seperti Snowflake atau BigQuery. Tapi arsitektur ini punya masalah fundamental: data harus diduplikasi dari OLTP ke OLAP, latency-nya tinggi, dan biayanya besar. Setiap engineering team punya ETL pipeline yang kompleks, dan setiap analytics team menunggu data warehouse untuk refresh tiap malam atau tiap jam.

Baru-baru ini, arsitektur LTAP (Lakehouse Transactional Analytical Processing) muncul sebagai jawaban. Konsepnya: bagaimana jika satu database bisa menangani keduanya — transaksi sehari-hari DAN analisis data — tanpa memindahkan data ke tempat lain? Yang menarik, Postgres — database open-source yang sudah mature — ternyata bisa menjadi fondasi arsitektur LTAP ini. Artikel ini akan membahas cara membangun arsitektur LTAP modern dengan Postgres, Apache Parquet untuk columnar storage, dan S3-compatible object storage untuk data lake. Kombinasi ini memberikan kemampuan analytics yang sebelumnya hanya bisa dicapai dengan data warehouse mahal, dengan budget startup Indonesia.

Perubahan Paradigma: Dari Database Tradisional ke Lakehouse

Konsep LTAP sebenarnya adalah evolusi dari dua tren yang sudah berjalan lama: data lake (penyimpanan file mentah yang murah dan fleksibel) dan data warehouse (penyimpanan terstruktur untuk analisis). Data lake menawarkan biaya penyimpanan rendah dan kebebasan format, tetapi kehilangan konsistensi transaksional. Data warehouse menawarkan konsistensi dan performa query, tetapi mahal dan kaku terhadap perubahan skema. LTAP menggabungkan keduanya: satu sistem yang mampu menjalankan transaksi OLTP sekaligus query analitis di atas data yang sama, tanpa proses duplikasi.

Dalam arsitektur ini, Postgres memegang peran sentral karena kemampuannya menjadi "jembatan" antara dua dunia: data transaksional tetap tinggal di Postgres, sementara data historis diekspor ke format Parquet dan disimpan di object storage. Alat bantu seperti DuckDB kemudian bisa membaca kedua sumber sekaligus dalam satu query. Hasilnya, tim engineering dan tim analytics bekerja di atas sumber data yang sama, dan masalah "data harus diduplikasi" yang mengganggu arsitektur tradisional bisa dihilangkan.

Memahami Format Parquet

Sebelum masuk ke arsitektur LTAP, ada baiknya memahami Apache Parquet. Parquet adalah columnar storage format yang dirancang untuk efisiensi:

  • Columnar storage: Data disimpan per kolom, bukan per baris. Query yang hanya butuh beberapa kolom tidak perlu membaca seluruh data.
  • Compression: Karena tipe data yang sama tersimpan berdekatan, compression ratio bisa mencapai 10x lebih baik dari row-based storage.
  • Schema evolution: Kolom bisa ditambah tanpa rewrite seluruh dataset.
  • Partition pruning: Query bisa skip partition yang tidak relevan.

Contoh konkret: tabel logs dengan 1 miliar baris dan 50 kolom. Query SELECT date, COUNT(*) FROM logs WHERE date > '2026-01-01' GROUP BY date — di Parquet hanya membaca kolom date, bukan seluruh 50 kolom. Query yang di Postgres biasa butuh 5 detik, di Parquet selesai dalam 200ms.

Arsitektur LTAP dengan Postgres

Arsitektur LTAP dengan Postgres didasarkan pada kemampuan Postgres untuk membaca dan menulis file Parquet langsung dari S3. Berikut komponen utamanya:

1. OLTP Layer — Postgres

Postgres tetap menjadi primary database untuk transaksi sehari-hari. Tabel-tabel utama seperti users, orders, products tetap berjalan di Postgres dengan performa OLTP yang sudah terbukti.

2. Data Lake Layer — Parquet on S3

Data dari Postgres di-export secara periodik ke format Parquet dan disimpan di S3 (atau MinIO untuk self-hosted). Ini menciptakan "lake" yang bisa diakses oleh tools analisis seperti DuckDB, Trino, atau Apache Spark.

3. Sync Layer — Change Data Capture (CDC)

Untuk sinkronisasi antara Postgres OLTP dan Parquet lake, gunakan CDC. Tools seperti Debezium atau pg_logical memonitor perubahan di Postgres dan mengupdate Parquet files secara near-real-time.

4. Query Layer — Hybrid Queries

Dengan setup yang benar, query yang menggabungkan data hot (di Postgres) dan data cold (di Parquet/S3) bisa dijalankan dalam satu query. Ini berguna untuk use case seperti query transaksi terakhir (hot) + analisis historical (cold), dashboard real-time dengan data bulanan, atau ML pipeline yang membutuhkan seluruh dataset. Untuk pola komunikasi real-time antar service, artikel Postgres LISTEN/NOTIFY untuk realtime event streaming tanpa Redis membahas pendekatan serupa yang bisa dikombinasikan dengan arsitektur LTAP ini.

Setup Practical: Postgres + Parquet + MinIO

Berikut setup yang pernah diimplementasikan untuk project e-commerce. Total waktu setup: sekitar 3 jam, termasuk testing.

Langkah 1: Setup MinIO sebagai S3-Compatible Storage

# docker-compose.yml untuk MinIO
version: '3.8'
services:
  minio:
    image: minio/minio:latest
    ports:
      - "9000:9000"
      - "9001:9001"
    environment:
      MINIO_ROOT_USER: minioadmin
      MINIO_ROOT_PASSWORD: minioadmin123
    volumes:
      - minio_data:/data
    command: server /data --console-address ":9001"
volumes:
  minio_data:

Langkah 2: Install DuckDB untuk Query Parquet

# DuckDB bisa query Parquet langsung dari S3
pip install duckdb psycopg2-binary

Langkah 3: Export Postgres ke Parquet

python3 << 'EOF'
import duckdb
con = duckdb.connect()

# Connect ke Postgres
con.execute("ATTACH 'dbname=myapp user=admin host=localhost' AS pg (TYPE postgres);")

# Export ke Parquet di S3 (via MinIO)
con.execute("""
    COPY (SELECT * FROM pg.public.orders 
          WHERE created_at > '2026-01-01')
    TO 's3://data-lake/orders/2026.parquet' 
    (FORMAT PARQUET, COMPRESSION 'ZSTD');
""")

# Export incremental per bulan
con.execute("""
    COPY (SELECT * FROM pg.public.orders 
          WHERE created_at >= '2026-07-01' 
          AND created_at < '2026-08-01')
    TO 's3://data-lake/orders/2026-07.parquet' 
    (FORMAT PARQUET, COMPRESSION 'ZSTD');
""")
EOF

Langkah 4: Query Hybrid

python3 << 'EOF'
import duckdb
con = duckdb.connect()

con.execute("ATTACH 'dbname=myapp user=admin host=localhost' AS pg (TYPE postgres);")

# Query hybrid: data historikal dari Parquet + data terbaru dari Postgres
result = con.execute("""
    WITH historical AS (
        SELECT DATE_TRUNC('month', created_at) as month,
               SUM(total) as revenue, COUNT(*) as orders
        FROM 's3://data-lake/orders/*.parquet'
        WHERE created_at < CURRENT_DATE - INTERVAL '30 days'
        GROUP BY 1
    ),
    recent AS (
        SELECT DATE_TRUNC('month', created_at) as month,
               SUM(total) as revenue, COUNT(*) as orders
        FROM pg.public.orders
        WHERE created_at >= CURRENT_DATE - INTERVAL '30 days'
        GROUP BY 1
    )
    SELECT * FROM historical UNION ALL SELECT * FROM recent ORDER BY month DESC
""").fetchall()

for row in result:
    print(f"{row[0]}: Revenue Rp{row[1]:,.0f} ({row[2]} orders)")
EOF

Biaya: Self-Hosted vs Cloud

ComponentCloud (AWS)Self-Hosted
S3 Storage (1TB)~$23/bulanMinIO di VPS existing = $0 tambahan
PostgresRDS t3.medium = ~$50/bulanVPS existing = $0 tambahan
Query EngineAthena per queryDuckDB = gratis
Total/bulan~$73+~$0 tambahan

Angka di atas mengasumsikan VPS existing sudah dipakai untuk aplikasi utama. Jika perlu VPS tambahan khusus storage atau query engine, VPS murah seperti RackNerd bisa menjadi pilihan dengan budget yang tetap terkendali — jauh lebih hemat daripada menambah instance RDS atau membayar Athena per query.

Kapan Harus Pakai Arsitektur Ini?

Gunakan LTAP ketika:

  • Data >10GB yang perlu dianalisis tapi tidak bisa dimuat semua ke RAM Postgres
  • Butuh query analytical yang kompleks (JOIN antara data terbaru dan historical)
  • Tim data butuh akses data langsung tanpa ETL pipeline kompleks
  • Budget terbatas dan tidak bisa pakai cloud data warehouse

Jangan pakai jika:

  • Data <1GB — cukup pakai Postgres biasa
  • Butuh real-time analytics (sub-second latency) — pertimbangkan ClickHouse
  • Tim tidak punya kemampuan technical untuk maintain infrastruktur

Setup Praktis: Postgres + Parquet + S3 dalam 30 Menit

Berikut setup minimum yang bisa dilakukan untuk mulai eksperimen dengan arsitektur LTAP. Tools yang dibutuhkan: Postgres 14+, DuckDB (sebagai query engine untuk Parquet), dan MinIO atau SeaweedFS untuk S3-compatible storage.

Step 1: Setup Postgres untuk OLTP

Pastikan Postgres sudah di-tune untuk workload campuran (OLTP + analytical). Parameter yang perlu di-adjust:

# postgresql.conf
shared_buffers = 4GB              # 25% dari total RAM
effective_cache_size = 12GB      # 75% dari total RAM
work_mem = 256MB                 # per-operation memory
maintenance_work_mem = 1GB       # untuk VACUUM, CREATE INDEX
max_parallel_workers_per_gather = 4
max_parallel_workers = 8
random_page_cost = 1.1           # untuk SSD
effective_io_concurrency = 200   # untuk SSD
wal_compression = on

Setelah adjust parameter, restart Postgres dan verifikasi dengan pg_stat_statements untuk monitor query performance. Untuk data yang perlu di-archive ke Parquet, gunakan partitioning by date — query terbaru tetap di main table, data lama di-partition ke file Parquet terpisah. Panduan lengkap setup Postgres di container tersedia di artikel Setup PostgreSQL di Docker.

Step 2: Export Data ke Parquet

Cara paling gampang: pakai DuckDB untuk query Postgres langsung dan export ke Parquet:

# Install duckdb
pip install duckdb

# Query Postgres dan export ke Parquet
duckdb -c "
INSTALL postgres;
LOAD postgres;
ATTACH 'dbname=mydb user=postgres host=localhost' AS pg (TYPE postgres);
COPY (
  SELECT * FROM pg.events
  WHERE event_date >= '2025-01-01'
) TO 'events_2025.parquet' (FORMAT PARQUET, COMPRESSION ZSTD);
"

File Parquet yang dihasilkan biasanya 5-10x lebih kecil dari CSV equivalent karena columnar compression. Query yang di SQL biasa butuh 30 detik, di Parquet bisa selesai dalam 200ms karena column pruning + predicate pushdown.

Step 3: Setup Object Storage (MinIO)

MinIO adalah S3-compatible storage yang bisa di-self-host. Install via Docker:

docker run -d \
  --name minio \
  -p 9000:9000 \
  -p 9001:9001 \
  -v /mnt/minio:/data \
  -e MINIO_ROOT_USER=admin \
  -e MINIO_ROOT_PASSWORD=secretpassword \
  quay.io/minio/minio server /data --console-address ":9001"

Setelah MinIO running, Parquet files bisa langsung di-query dari S3-compatible endpoint dengan DuckDB:

duckdb -c "
INSTALL httpfs;
LOAD httpfs;
SET s3_endpoint='minio.local:9000';
SET s3_access_key_id='admin';
SET s3_secret_access_key='secretpassword';
SET s3_use_ssl=false;
SELECT date, COUNT(*) FROM read_parquet('s3://mybucket/events/*.parquet') GROUP BY date;
"

Step 4: Setup Hybrid Query Layer

Power utama arsitektur LTAP: query yang menggabungkan data fresh dari Postgres dan historical dari Parquet. Pakai Postgres foreign data wrapper atau DuckDB yang support langsung:

-- Query: data terbaru dari Postgres, data historis dari Parquet
WITH recent_events AS (
  SELECT * FROM events WHERE created_at >= NOW() - INTERVAL '7 days'
),
historical_events AS (
  SELECT * FROM read_parquet('s3://mybucket/events/2025-*.parquet')
)
SELECT date_trunc('day', created_at) AS day, COUNT(*)
FROM (
  SELECT * FROM recent_events
  UNION ALL
  SELECT * FROM historical_events
) combined
GROUP BY day
ORDER BY day;

Query ini secara otomatis pakai data Postgres untuk 7 hari terakhir dan Parquet untuk data historis. Tidak perlu ETL pipeline yang memindahkan data — semua on-demand. Untuk dashboard yang query 1000+ kali per hari, cache layer bisa ditambahkan di antara.

Optimasi Lanjutan: Indexing dan Partitioning

Untuk table yang sangat besar (ratusan juta row), partitioning by date adalah wajib. Postgres declarative partitioning:

CREATE TABLE events (
  id BIGSERIAL,
  event_date DATE NOT NULL,
  user_id INTEGER,
  data JSONB
) PARTITION BY RANGE (event_date);

CREATE TABLE events_2026_q3 PARTITION OF events
  FOR VALUES FROM ('2026-07-01') TO ('2026-10-01');
CREATE TABLE events_2026_q4 PARTITION OF events
  FOR VALUES FROM ('2026-10-01') TO ('2027-01-01');

Dengan partitioning, query yang filter by date hanya scan partition yang relevan, bukan seluruh table. Drop partition lama juga instant karena cuma metadata operation. Untuk data yang lebih dari 1 tahun, archive partition ke Parquet dan hapus dari Postgres — ini cara paling efektif untuk manage long-term data storage.

Monitoring dan Observability untuk LTAP Stack

Stack LTAP yang kompleks butuh monitoring yang tepat. Metrics yang wajib di-track:

  • Postgres: query latency, connection count, replication lag, cache hit ratio.
  • Object storage: storage usage, request rate, latency per operation.
  • Query engine (DuckDB): query duration, memory usage per query, cache hit rate.
  • ETL jobs (kalau pakai): success rate, duration, lag behind source.

Tools yang cocok: pgWatch untuk Postgres, MinIO built-in metrics + Prometheus exporter, custom instrumentation untuk DuckDB. Visualisasi di Grafana dengan dashboard yang menampilkan trend. Alerting: kalau query latency p95 > 5 detik, atau storage usage > 80% kapasitas, kirim notifikasi ke tim. Panduan lengkap membangun stack monitoring self-hosted ada di artikel Monitoring server self-hosted dengan Netdata, Grafana, dan Prometheus.

Real-World Use Case: Analytics untuk SaaS

Arsitektur ini pernah diimplementasikan untuk SaaS analytics platform dengan 50 juta event per bulan. Data flow:

  1. Event masuk ke Postgres (current quarter) untuk real-time query.
  2. Data > 90 hari di-export ke Parquet di S3.
  3. Dashboard analytics query via DuckDB yang transparan combine keduanya.
  4. Total biaya: $80/bulan untuk 2TB data — jauh lebih murah dari Snowflake ($1,500+/bulan untuk dataset equivalent).

Performance: query dashboard rata-rata 800ms (Postgres-only) untuk data minggu ini, 3-4 detik (hybrid) untuk query yang butuh 6 bulan data. Snowflake biasanya 1-2 detik untuk query equivalent — sedikit lebih cepat, tapi biaya 18x lebih mahal. Buat early-stage SaaS, trade-off ini sangat worth it.

Sebagai perbandingan, langganan data warehouse cloud bisa menghabiskan ratusan dolar per bulan untuk kapasitas serupa. Sisa budget tersebut bisa dialokasikan ke VPS atau hosting yang mumpuni, misalnya dari RackNerd, sehingga biaya infrastruktur tetap predictable dan tidak ada vendor lock-in.

Kesimpulan

Arsitektur LTAP dengan Postgres, Parquet, dan S3 itu bukan sekadar teori — ini production-ready pattern yang sudah battle-tested di banyak startup. Dengan setup awal yang relatif straightforward (Postgres yang sudah ada + DuckDB + MinIO), data analytics capability yang biasanya hanya bisa dicapai dengan data warehouse mahal bisa dimiliki dengan biaya minimal. Yang paling penting: full control atas data tetap di tangan sendiri, tidak ada vendor lock-in, dan biaya infrastructure yang predictable. Buat developer Indonesia yang lagi bangun data-driven product, ini pattern yang wajib dikuasai.

Kunci suksesnya: Postgres untuk OLTP, Parquet untuk columnar storage, S3/MinIO untuk object storage, dan DuckDB untuk hybrid queries. Dengan komposisi ini, sistem data yang sebelumnya hanya dimiliki oleh perusahaan besar bisa dibangun dengan budget startup Indonesia.

Sumber dan Validasi

Catatan: Artikel ini disusun berdasarkan dokumentasi resmi Apache Parquet, DuckDB, dan pengumuman arsitektur LTAP dari Databricks. Angka biaya bersifat estimasi berdasarkan harga publik per tanggal penulisan dan bisa berubah sewaktu-waktu.

💬 Komentar (0)

Belum ada komentar. Jadilah yang pertama! 💬

Komentar akan muncul setelah moderasi.