Jika tim Anda sedang membangun platform AI internal untuk developer productivity—misalnya chatbot internal, prompt log, policy enforcement, billing per tim, cache respons model, dan observability—pertanyaan utamanya bukan apakah harus langsung memakai microservices. Pertanyaannya adalah: arsitektur mana yang memberi kecepatan delivery terbaik hari ini tanpa menciptakan beban operasional yang tidak perlu enam bulan ke depan.
Jawaban praktisnya: untuk tim kecil-menengah, mulai dari monolit yang rapi atau modular monolith biasanya lebih masuk akal daripada microservices penuh. Microservices baru layak ketika ada kebutuhan nyata pada isolasi kegagalan, skala tim, atau karakter workload yang benar-benar berbeda. Artikel ini membahas trade-off teknisnya dengan konteks platform AI internal, bukan aplikasi CRUD biasa.
Konteks tren seperti “vibecoding” sering mendorong tim untuk cepat membuat fitur AI bagi developer. Itu bagus sebagai pemicu use case, tetapi keputusan arsitektur tetap harus mengikuti batas domain, beban operasional, dan pola perubahan sistem.
Apa yang Sebenarnya Dibangun oleh Platform AI Internal?
Sebelum membahas bentuk arsitektur, kita perlu menyepakati scope. Platform AI internal untuk developer umumnya bukan hanya endpoint ke model LLM. Ia biasanya berkembang menjadi kumpulan kapabilitas berikut:
- Chat/API gateway: menerima request dari web app, CLI, IDE plugin, atau bot internal.
- Prompt log: menyimpan prompt, metadata, latency, token usage, output, dan status.
- Policy: redaksi data sensitif, allowlist model, batas ukuran input, approval policy, audit.
- Billing/showback: akumulasi penggunaan per user, tim, cost center, atau proyek.
- Cache: response cache, semantic cache, atau dedup untuk request identik.
- Observability: metrics, tracing, log terstruktur, alert, dashboard kualitas dan biaya.
- Provider adapter: integrasi ke beberapa model/provider dengan fallback.
Masalahnya, fitur-fitur ini terlihat seperti kandidat service terpisah. Padahal, pada tahap awal mereka sering berbagi:
- model data yang sama,
- alur request yang sama,
- aturan policy yang saling bergantung,
- kebutuhan debugging lintas fitur dalam satu transaksi.
Karena itu, memecah terlalu dini justru bisa memperlambat delivery.
Tiga Pendekatan Arsitektur untuk Platform AI Internal
1) Monolit
Monolit berarti seluruh kapabilitas utama berjalan dalam satu aplikasi deployable. Bisa saja ada satu database utama, satu pipeline deployment, satu repositori, dan satu proses aplikasi atau sekumpulan proses yang masih menjadi satu unit rilis.
Untuk platform AI internal, monolit sering berarti:
- satu API backend,
- satu skema database utama,
- satu mekanisme auth,
- job async tetap ada, tetapi masih dikelola dari codebase yang sama.
Kelebihan:
- Biaya operasional rendah: deployment, monitoring, secret management, dan CI/CD lebih sederhana.
- Debugging lebih mudah: satu trace request bisa diikuti tanpa melompat antar-service.
- Refactor cepat: perubahan skema data dan API internal lebih mudah dilakukan bersama.
- Cocok untuk tim kecil: lebih sedikit koordinasi antar-owner.
Kekurangan:
- Risk blast radius lebih besar: bug pada modul billing atau logging bisa memengaruhi jalur chat jika isolasinya buruk.
- Scaling tidak selektif: komponen berat seperti ingestion log atau cache warmer ikut menempel pada unit yang sama.
- Batas domain mudah kabur jika disiplin modularitas lemah.
2) Modular Monolith
Modular monolith adalah monolit dengan batas domain yang tegas di level codebase. Aplikasi tetap satu unit deploy, tetapi di dalamnya dibagi ke modul dengan kontrak yang jelas: dependency direction, API internal, kepemilikan data, dan event internal.
Ini sering menjadi titik tengah terbaik untuk platform AI internal.
Kelebihan:
- Masih murah dioperasikan seperti monolit.
- Lebih siap tumbuh: batas domain sudah ada sejak awal.
- Migrasi ke service lebih aman bila suatu modul benar-benar perlu dipisah.
- Testing lebih sehat: unit test dan integration test bisa mengikuti modul, bukan seluruh aplikasi.
Kekurangan:
- Perlu disiplin engineering: jika semua modul bebas mengakses tabel dan utilitas satu sama lain, modular monolith hanya jadi monolit biasa dengan folder lebih banyak.
- Isolasi kegagalan masih terbatas: crash process tetap memukul semua modul dalam unit deploy yang sama.
3) Microservices
Microservices memisahkan kapabilitas menjadi service deployable yang independen. Masing-masing service idealnya punya ownership domain, data, deployment, observability, dan lifecycle sendiri.
Untuk platform AI internal, contoh bentuknya bisa berupa service terpisah untuk chat gateway, policy engine, usage ledger, prompt log ingestion, dan cache API.
Kelebihan:
- Isolasi kegagalan lebih baik jika dirancang benar.
- Scaling lebih selektif: prompt log ingestion bisa diskalakan berbeda dari chat API.
- Otonomi tim lebih tinggi pada organisasi yang sudah memiliki beberapa squad backend/platform.
Kekurangan:
- Biaya operasional naik tajam: service discovery, network policy, observability terdistribusi, CI/CD per service, secret rotation, dan kontrak API.
- Kompleksitas debugging lebih tinggi: masalah timeout, retry storm, idempotency, partial failure, dan version skew menjadi pekerjaan harian.
- Data consistency lebih sulit: billing, policy, dan logging sering butuh sinkronisasi lintas domain.
Perbandingan Praktis: Monolit vs Modular Monolith vs Microservices
| Aspek | Monolit | Modular Monolith | Microservices |
|---|---|---|---|
| Kecepatan delivery awal | Tinggi | Tinggi | Rendah-sedang |
| Biaya operasional | Rendah | Rendah-sedang | Tinggi |
| Kompleksitas deployment | Rendah | Rendah | Tinggi |
| Isolasi kegagalan | Rendah | Rendah-sedang | Sedang-tinggi |
| Skalabilitas tim | Rendah-sedang | Sedang-tinggi | Tinggi |
| Maintainability jangka panjang | Tergantung disiplin | Baik | Baik jika organisasi siap |
| Kompleksitas data consistency | Rendah | Rendah | Tinggi |
| Observability | Relatif mudah | Mudah | Wajib matang |
Kesimpulan praktis dari tabel di atas: modular monolith sering menjadi default yang paling rasional untuk tim kecil-menengah yang membangun platform AI internal serius tetapi belum punya kebutuhan operasional setara perusahaan besar.
Batas Domain yang Masuk Akal untuk Platform AI Internal
Jika Anda memilih modular monolith atau menyiapkan jalan ke microservices, tentukan batas domain berdasarkan perubahan bisnis, kepemilikan data, dan pola beban kerja, bukan hanya berdasarkan nama fitur di UI.
Contoh bounded context yang sehat
- Conversation Runtime: menerima request chat/completion, menyusun context, memanggil provider, menangani streaming respons.
- Policy & Guardrails: validasi input, masking data sensitif, model allowlist, approval dan audit decision.
- Usage & Billing: pencatatan token/cost per request, agregasi per tim, kuota, limit, showback.
- Prompt Log & Audit: penyimpanan request/response metadata, status, jejak kepatuhan, retention.
- Caching: response cache, key strategy, invalidation, dedup.
- Observability: metrics, distributed tracing, event quality, dashboard operasi.
- Provider Integration: adapter ke beberapa model vendor atau model internal.
Batas domain yang kurang sehat
- Service terpisah hanya karena “fitur ini terlihat penting”.
- Memecah berdasarkan lapisan teknis seperti auth service, db service, logging service padahal belum ada ownership domain jelas.
- Memisahkan billing terlalu cepat saat datanya masih sepenuhnya berasal dari alur chat yang sama dan belum butuh pemrosesan independen.
Aturan praktis: pisahkan domain ketika perubahan, skala, atau kegagalannya memang perlu dipisah.
Rekomendasi Implementasi: Mulai dari Modular Monolith
Untuk kebanyakan tim, pendekatan terbaik adalah:
- bangun satu aplikasi inti,
- pisahkan modul secara ketat di level codebase,
- gunakan event internal atau queue untuk pekerjaan async,
- ekstrak service hanya jika ada sinyal kuat.
Struktur modul yang sederhana
src/
modules/
runtime/
api/
application/
domain/
infra/
policy/
api/
application/
domain/
infra/
usage/
api/
application/
domain/
infra/
promptlog/
api/
application/
domain/
infra/
cache/
api/
application/
domain/
infra/
provider/
api/
application/
domain/
infra/
shared/
auth/
db/
queue/
observability/Intinya bukan nama foldernya, tetapi aturan berikut:
- modul tidak mengakses tabel modul lain secara sembarangan,
- komunikasi antar-modul lewat interface atau event internal,
- logika domain tidak bergantung pada detail HTTP atau vendor SDK,
- code observability terstandarisasi sejak awal.
Contoh alur request yang realistis
- Client mengirim request chat.
- Runtime memanggil Policy untuk validasi input dan pemilihan model.
- Runtime mengecek Cache.
- Jika cache miss, Runtime memanggil Provider adapter.
- Setelah respons diterima, Runtime mengirim event internal:
PromptLoggedke modul prompt log,UsageRecordedke modul billing/usage,TraceAnnotatedke observability.
Dengan pola ini, jalur utama tetap sederhana, tetapi pekerjaan non-kritis bisa diproses async.
Contoh kontrak event internal
{
"eventType": "UsageRecorded",
"requestId": "req_123",
"workspaceId": "team_abc",
"userId": "u_42",
"provider": "provider-x",
"model": "general-chat",
"inputTokens": 1200,
"outputTokens": 350,
"estimatedCost": 0.0,
"timestamp": "2026-08-07T10:15:00Z"
}Formatnya tidak harus persis seperti ini, tetapi pastikan ada request ID, actor, workspace, model, dan metadata penggunaan agar debugging dan showback tidak kacau.
Kapan Monolit Sudah Cukup?
Pilih monolit sederhana jika kondisi Anda seperti berikut:
- tim backend masih 2-5 orang,
- fitur inti belum stabil dan masih banyak eksperimen product,
- semua request masih melewati alur yang sangat mirip,
- belum ada workload berat yang benar-benar berbeda,
- insiden lebih sering berasal dari logika aplikasi daripada batas skalabilitas.
Pada tahap ini, biaya terbesar biasanya bukan CPU atau jaringan, melainkan perubahan requirement. Monolit membuat refactor lebih murah selama codebase dijaga tetap bersih.
Kapan Modular Monolith Menjadi Pilihan Terbaik?
Pilih modular monolith jika:
- fitur mulai bertambah: chat, policy, usage, prompt log, cache, observability, admin panel,
- beberapa engineer mulai bekerja paralel di area berbeda,
- Anda ingin menjaga kemungkinan ekstraksi service di masa depan,
- Anda butuh struktur ownership tanpa overhead jaringan antar-service.
Ini sering menjadi sweet spot untuk platform AI internal. Anda mendapatkan struktur yang sehat tanpa langsung menanggung beban distributed systems.
Kapan Microservices Layak Dipertimbangkan?
Gunakan microservices hanya jika ada sinyal yang konsisten, bukan karena asumsi “nanti pasti besar”. Beberapa sinyal yang masuk akal:
- Workload berbeda drastis: prompt log ingestion atau analytics jauh lebih berat daripada traffic chat sinkron.
- Isolasi kegagalan sangat penting: kegagalan billing atau audit export tidak boleh memengaruhi request chat utama.
- Tim bertambah dan ownership jelas: ada squad terpisah untuk runtime, governance, dan usage platform.
- Rilis independen benar-benar dibutuhkan: policy engine harus dapat berubah lebih cepat dengan kontrol deployment sendiri.
- Batas data makin tegas: domain usage ledger menjadi sistem of record tersendiri dengan lifecycle retensi dan rekonsiliasi berbeda.
Tanpa sinyal-sinyal itu, microservices sering hanya memindahkan kompleksitas dari codebase ke jaringan dan operasi.
Matriks Keputusan untuk Tim Kecil-Menengah
| Kondisi | Pilihan yang Disarankan | Alasan |
|---|---|---|
| MVP internal, 1-3 engineer, scope cepat berubah | Monolit | Refactor cepat, overhead operasi minimum |
| Produk mulai dipakai banyak tim internal, fitur governance bertambah | Modular Monolith | Batas domain mulai penting, tapi belum perlu jaringan antar-service |
| Traffic log/analytics berat, jalur sinkron harus stabil | Modular Monolith + async workers | Sering cukup tanpa microservices penuh |
| Beberapa domain butuh skala dan rilis independen | Selective Microservices | Ekstrak hanya domain yang punya alasan kuat |
| Organisasi punya platform engineering matang dan observability baik | Microservices | Overhead operasional sudah bisa ditanggung |
Pola Migrasi yang Aman
Jangan migrasi dari monolit ke microservices sebagai proyek besar sekali jalan. Lakukan bertahap.
Tahap 1: Rapikan monolit
- pisahkan modul,
- tutup akses langsung ke data modul lain,
- standarkan request ID, trace ID, dan event.
Tahap 2: Asinkronkan pekerjaan non-kritis
- prompt logging, agregasi usage, notifikasi audit, export analytics.
Sering kali ini sudah menyelesaikan bottleneck utama tanpa memecah service.
Tahap 3: Ekstrak domain yang benar-benar cocok
Kandidat pertama biasanya prompt log ingestion atau usage aggregation, karena keduanya:
- bervolume tinggi,
- toleran async,
- punya kebutuhan scale berbeda dari request chat sinkron.
Tahap 4: Stabilkan kontrak
Sebelum domain diekstrak, pastikan ada kontrak yang eksplisit:
- schema event,
- idempotency key,
- timeout dan retry policy,
- ownership data,
- mekanisme rekonsiliasi jika event hilang atau duplikat.
Anti-Pattern: Memecah Service Terlalu Cepat
1) Satu fitur, satu service
Chat service, prompt service, billing service, cache service, observability service, policy service—terdengar rapi di diagram, tetapi sering kacau di operasional. Setiap request chat menjadi rantai hop jaringan yang panjang, dan satu timeout kecil bisa memperburuk pengalaman pengguna.
2) Shared database antar-service
Ini menghilangkan manfaat utama microservices. Kalau beberapa service bebas membaca/menulis tabel yang sama, Anda mendapatkan kompleksitas service tanpa independensi nyata.
3) Synchronous everything
Billing, logging, audit, dan analytics tidak selalu harus sinkron di jalur request utama. Memaksa semuanya sinkron membuat latency naik dan blast radius membesar.
4) Ekstraksi berdasarkan org chart, bukan domain
Jika service boundaries dibuat hanya karena pembagian tim sementara, hasilnya sering berubah-ubah dan kontraknya rapuh.
5) Tidak punya observability sebelum microservices
Memecah service tanpa trace lintas request, log terstruktur, dan metric yang konsisten akan membuat debugging jauh lebih sulit daripada saat masih monolit.
Concern Teknis yang Sering Terlewat
Idempotency untuk billing dan logging
Request ke provider bisa retry, worker bisa memproses ulang event, dan callback bisa datang dua kali. Pastikan pencatatan usage dan prompt log menggunakan idempotency key, misalnya kombinasi request ID dan event type.
Policy jangan ditanam acak di banyak tempat
Kesalahan umum adalah menaruh aturan masking, model allowlist, dan kuota di gateway, service runtime, dan UI sekaligus tanpa sumber kebenaran jelas. Simpan decision logic pada satu modul/domain yang otoritatif.
Cache invalidation harus berbasis use case
Untuk AI platform, cache bukan sekadar key-value sederhana. Anda perlu jelas tentang:
- apa yang boleh di-cache,
- apakah policy ikut memengaruhi cache key,
- bagaimana menangani perubahan prompt template atau system prompt.
Jika policy atau context berubah, respons lama bisa menjadi tidak valid walau input user sama.
Provider adapter harus menahan vendor lock-in teknis
Jangan bocorkan detail SDK vendor ke seluruh codebase. Bungkus perbedaan provider di adapter atau gateway internal. Ini mempermudah fallback, testing, dan migrasi model.
Tips Debugging di Dunia Nyata
- Selalu bawa request ID dari ingress sampai logging usage dan audit event.
- Catat keputusan policy, bukan hanya hasil akhir. Misalnya: model dipilih karena policy tertentu, prompt dipotong karena batas token, request diblokir karena data sensitif.
- Bedakan latency provider dan latency platform. Jika lambat, pastikan apakah bottleneck ada di model, cache, policy, database, atau worker queue.
- Simpan metadata secukupnya untuk investigasi tanpa melanggar kebijakan data internal.
- Uji partial failure: bagaimana jika provider timeout, billing worker down, atau storage prompt log bermasalah?
Contoh Keputusan yang Masuk Akal untuk Tim 5-12 Engineer
Jika saya harus memberi baseline implementatif untuk tim kecil-menengah yang membangun platform AI internal developer, saya akan memilih:
- Modular monolith sebagai inti platform,
- satu database utama untuk data transaksional,
- queue/workers untuk prompt log, usage aggregation, dan notifikasi audit,
- Redis atau cache serupa untuk dedup/request cache bila memang perlu,
- provider adapter layer agar integrasi model tidak menyebar,
- observability konsisten sejak hari pertama: structured logs, traces, metrics.
Lalu, ekstrak service hanya untuk domain yang menunjukkan tekanan nyata, biasanya ingestion atau analytics. Bukan karena diagram arsitektur terlihat lebih modern.
Kesimpulan
Dalam arsitektur platform AI internal, pilihan terbaik jarang dimulai dari microservices penuh. Untuk fitur seperti chat, prompt log, policy, billing, cache, dan observability, monolit yang rapi cocok untuk fase awal, sedangkan modular monolith adalah pilihan paling seimbang untuk pertumbuhan tim kecil-menengah.
Microservices masuk akal ketika ada alasan operasional yang nyata: workload sangat berbeda, kebutuhan isolasi kegagalan tinggi, ownership tim kuat, dan observability sudah matang. Sampai titik itu tercapai, fokuslah pada batas domain yang bersih, event internal yang jelas, dan operasi yang sederhana. Untuk platform AI internal, arsitektur yang paling berguna bukan yang paling trendi, tetapi yang mempercepat delivery tanpa mengorbankan maintainability.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!