Alphazed menjalankan seluruh backend-nya — melayani lebih dari 95.000 siswa di lebih dari 50 negara — menggunakan AWS Lambda dengan Serverless Framework. Arsitektur menggunakan Flask di Lambda di belakang API Gateway, MySQL 8 di RDS, S3 untuk pengiriman konten, dan analytics lake khusus (SQS → Kinesis Firehose → S3 → Glue → Athena). Handler Lambda ringan mengoptimalkan latensi cold-start, dan sistem melayani 7+ aplikasi dari satu basis kode dengan pengaturan konfigurasi runtime.
Mengapa Serverless untuk EdTech?
Aplikasi pendidikan memiliki pola penggunaan yang tidak dapat diprediksi:
- Pagi hari kerja: Orang tua mengunduh aplikasi sebelum mengantar anak ke sekolah (lonjakan traffic)
- Sore hari kerja: Sesi latihan setelah sekolah (beban berkelanjutan)
- Akhir pekan: Sesi maraton intensif (2-3x beban normal)
- Selama Ramadan: Penggunaan malam hari meningkat pesat (sesi keluarga mengaji Quran)
- Liburan sekolah: Pola berbeda sama sekali
Kelebihan Serverless:
- Harga bayar per permintaan: Anda hanya membayar untuk penggunaan sebenarnya. Jika 10 pengguna mengakses API, bayar 10 kali pemanggilan. Jika 100.000 pengguna saat viral, langsung bisa skalasi.
- Tanpa cold start untuk endpoint frekuensi tinggi: Kami menggunakan layer Lambda "selalu hangat" untuk endpoint yang sering dipanggil
- Auto-scaling: Tangani 10 hingga 10.000 pengguna bersamaan tanpa perubahan infrastruktur
- Tanpa pemeliharaan server: Tim fokus pada kurikulum dan AI, bukan cluster Kubernetes atau load balancer
Pembahasan Arsitektur
API Gateway → Lambda → RDS
[Client App] (iOS, Android, Web)
↓
[API Gateway] (pengaturan HTTP, pembatasan rate)
↓
[Lambda Handlers] (aplikasi Flask, memori 512MB, timeout 28 detik)
├── Rute aplikasi: /app/* (endpoint mobile)
├── Rute pengguna: /user/* (endpoint terautentikasi)
└── Rute admin: /boss/* (dashboard admin)
↓
[MySQL 8 di RDS] (data persisten)
↓
[Respons] (JSON kembali ke client)
Lambda Ringan untuk Kecepatan
Kebanyakan Lambda sengaja dibuat sangat minimal:
# Handler ringan (~100KB)
import json
import pymysql
def get_user_progress(event, context):
user_id = event['pathParameters']['user_id']
# Koneksi DB langsung (tanpa overhead ORM)
conn = pymysql.connect(host='rds.aws.com', user='app', password='...', database='amal')
cursor = conn.cursor()
cursor.execute(
'SELECT concept_id, accuracy FROM user_memory WHERE user_id = %s',
(user_id,)
)
rows = cursor.fetchall()
conn.close()
return {
'statusCode': 200,
'body': json.dumps([{'concept': r[0], 'accuracy': r[1]} for r in rows])
}
Tidak ada import Flask, tidak ada SQLAlchemy ORM, tanpa middleware. Hasil: ~500ms cold start dibandingkan 5-10 detik untuk aplikasi Flask penuh.
Endpoint berat (pembuatan konten, pemrosesan analytics) menggunakan Flask lengkap:
# Handler berat (~30MB dengan Flask, SQLAlchemy, numpy)
dari flask import Flask, jsonify
dari models import UserMemory
import numpy sebagai np
app = Flask(name)
@app.route('/content_duo/generate', methods=['POST'])
def generate_content_duo():
# Logika kompleks membutuhkan ORM
user = UserMemory.query.filter_by(user_id=request.json['user_id']).first()
# ... buat sesi personalisasi ...
return jsonify(session_data)
Tukarannya: cold start lebih lambat, tapi dipanggil lebih jarang.
Prefiks Tabel Per-Aplikasi
Satu instance RDS melayani 7+ aplikasi dengan isolasi tingkat basis data:
-- Amal app
CREATE TABLE amal_users (...)
CREATE TABLE amal_content_bytes (...)
CREATE TABLE amal_user_memory (...)
-- Thurayya app
CREATE TABLE thurayya_users (...)
CREATE TABLE thurayya_content_bytes (...)
CREATE TABLE thurayya_user_memory (...)
-- Aplikasi lain: qais_, kidelite_, dll.
Pada waktu deploy, variabel lingkungan APP_NAME memilih prefiks:
app_name = os.getenv('APP_NAME', 'amal') # 'amal', 'thurayya', 'qais', dll.
Query menggunakan prefiks secara dinamis
table_name = f'{app_name}_users'
cursor.execute(f'SELECT * FROM {table_name} WHERE id = %s', (user_id,))
The Analytics Lake
Masalah: Query database langsung untuk analytics memperlambat produksi. Menjalankan laporan mengunci tabel.
Solusi: Pipeline analytics asinkron
[Mobile App]
↓ (kirim event)
[API Endpoint] → [SQS Queue] (asinkron)
↓ (respon langsung ke app)
↓ (tidak menunggu analytics)
[Kinesis Firehose] (mengumpulkan event setiap 5 menit atau saat mencapai 100MB)
↓
[S3] (terpartisi: s3://analytics-lake/amal/2026/03/28/events.parquet)
↓
[AWS Glue] (crawl S3, infers schema)
↓
[Athena] (query SQL dengan mesin Presto)
↓
[Dashboard] (menampilkan insight waktu nyata)
Polanya Dead Letter Queue (DLQ)
Jika analytics gagal:
SQS → [Firehose gagal]
↓
[DLQ menerima pesan gagal]
↓
[Peringatan dikirim ke ops]
↓
[API produksi tidak terganggu]
Analytics tidak pernah menghambat permintaan pengguna. Anak-anak bisa belajar walau pipeline analytics sedang down.
Strategi Optimasi Biaya
Strategi 1: Lambda ringan untuk endpoint frekuensi tinggi
- Aplikasi mobile biasa membuat 10–20 panggilan API per sesi
- 95.000 pengguna aktif × 3 sesi/hari × 15 panggilan/sesi = 4,275 juta panggilan/hari
- Jika tiap panggilan biaya $0,0000002 (harga Lambda), total sekitar $0,86/hari
- Mengurangi cold start 10 detik menghemat sekitar $500/bulan
Strategi 2: RDS Reserved Instance
- Reservasi komitmen 3 tahun: diskon sekitar 60% dibanding bayar sesuai pakai
- Kami menggunakan
db.r6i.xlarge(4 vCPU, 32GB RAM): $2.800/bulan reserved vs $6.500/bulan on-demand - Penghematan tahunan sekitar $50.000
Strategi 3: Caching
- Data yang sering diakses (kurikulum, konten bytes) dicache di ElastiCache (Redis)
- Mengurangi query RDS sekitar 70%
- Biaya cache $800/bulan, menghemat $2.000/bulan di RDS
Melayani 7+ Aplikasi dari Satu Basis Kode
| Aplikasi | Prefiks | Tabel DB | Stack Lambda | Status |
|---|---|---|---|---|
| Amal | amal_ | 40+ tabel | Bersama | Produksi |
| Thurayya | thurayya_ | 40+ tabel | Bersama | Produksi |
| Qais | qais_ | 35+ tabel | Bersama | Beta |
| KidElite | kidelite_ | 40+ tabel | Bersama | Produksi |
| Alphazed School | school_ | 50+ tabel | Bersama | Beta |
| Alphazed Montessori | montessori_ | 45+ tabel | Bersama | Internal |
Satu backend, satu pipeline deploy, 6 aplikasi berjalan bersamaan. Peluncuran aplikasi baru beberapa minggu, bukan bulan.
FAQ
T: Bukankah Lambda punya batas waktu maksimum 15 menit?
J: Lambda maks timeout 15 menit, tapi kami jarang butuh request lama. Beban berat (pembuatan konten, ekspor besar) menggunakan job asinkron dengan SQS + Step Functions.
T: Bagaimana jika database gagal?
J: RDS memiliki failover Multi-AZ (primary + replica standby). Failover otomatis dalam sekitar 60 detik. Client mungkin mengalami timeout singkat tapi pemulihan cepat.
T: Bagaimana mengelola connection pool database dengan Lambda stateless?
J: Setiap instance Lambda mempertahankan connection pool (dipakai ulang selama invocation hangat). Cold start buka koneksi baru. RDS Proxy antara Lambda dan RDS mengatur limit koneksi.



