Merancang Pipeline Face Recognition sebagai Microservice: Kenapa Laravel Jadi Orkestrator
Keputusan arsitektur di balik Gym Management System: memisahkan inference ML ke FastAPI, tapi menjadikan Laravel satu-satunya pintu masuk.
Saat membangun fitur check-in wajah untuk Gym Management System, keputusan teknis yang paling menentukan bukan model ML yang dipakai — melainkan di mana inference berjalan dan siapa yang boleh memanggilnya.
Dua opsi arsitektur
Opsi pertama yang paling cepat dikerjakan: kiosk (Next.js) memanggil microservice face recognition (FastAPI) secara langsung. Latensi minimal, kode sedikit.
Opsi kedua: semua permintaan lewat backend Laravel, dan Laravel yang memanggil FastAPI secara server-to-server.
Saya memilih opsi kedua, dan artikel ini menjelaskan alasannya.
Alasan 1: Data biometrik tidak bisa "direset"
Password yang bocor bisa diganti. Embedding wajah tidak. Kalau endpoint ML terekspos publik, setiap bug otorisasi di service Python berpotensi membocorkan data paling sensitif di sistem. Dengan Laravel sebagai satu-satunya pintu:
- FastAPI berjalan di jaringan internal, tidak punya route publik sama sekali.
- Otorisasi cukup diimplementasikan sekali, di Laravel (JWT + RBAC), bukan dua kali di dua bahasa.
- Embedding disimpan terenkripsi di PostgreSQL; microservice bersifat stateless.
Alasan 2: Audit dan orkestrasi bisnis
Check-in bukan sekadar "wajah cocok". Ada aturan bisnis: apakah membership aktif? Apakah sudah check-in hari ini? Semua aturan itu hidup di Laravel. Alur lengkapnya:
public function identify(UploadedFile $photo): CheckInResult
{
// 1. Quality gate: tolak foto blur/gelap sebelum masuk pipeline
$response = $this->faceClient->post('/identify', [
'image' => $photo->getContent(),
]);
// 2. Cocokkan embedding dengan data member (cosine similarity)
$member = $this->matchEmbedding($response->embedding());
// 3. Aturan bisnis: membership aktif + belum check-in hari ini
$this->assertEligible($member);
return $this->attendance->checkIn($member);
}Kalau kiosk memanggil FastAPI langsung, langkah 2 dan 3 harus dititipkan ke service ML — mencampur concern yang seharusnya terpisah.
Alasan 3: Beban kerja yang berbeda, scaling yang berbeda
Inference ONNX (SCRFD untuk deteksi + ArcFace untuk embedding 512-dimensi) bersifat CPU-bound dan lonjakannya mengikuti jam ramai gym. CRUD bisnis tidak. Dengan memisahkannya:
Klien (web/mobile/kiosk) ──► Laravel API ──► FastAPI (internal)
│ │
PostgreSQL ONNX RuntimeFastAPI bisa diberi resource lebih besar atau direplikasi saat jam sibuk, tanpa menyentuh deployment Laravel.
Trade-off yang diterima
Arsitektur ini menambah satu hop jaringan (kiosk → Laravel → FastAPI), artinya latensi ekstra puluhan milidetik. Untuk use case check-in — yang targetnya "di bawah beberapa detik", bukan real-time — itu harga yang sangat murah untuk keamanan dan kerapian yang didapat.
Kesimpulan
Kalau ada satu prinsip yang saya bawa dari proyek ini: letakkan keputusan keamanan di arsitektur, bukan di kode. Endpoint yang tidak pernah terekspos tidak perlu ditambal.