Serverless Skala Besar: Menjalankan EdTech Bahasa Arab di AWS Lambda
Baca 5 mntMohammad Shaker

Serverless Skala Besar: Menjalankan EdTech Bahasa Arab di AWS Lambda

Alphazed menjalankan backend dengan AWS Lambda melayani 95.000+ siswa menggunakan Flask, MySQL, dan analytics kustom untuk pendidikan Arab.

Engineering

Jawaban Singkat

Alphazed menjalankan backend dengan AWS Lambda melayani 95.000+ siswa menggunakan Flask, MySQL, dan analytics kustom untuk pendidikan Arab.

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

AplikasiPrefiksTabel DBStack LambdaStatus
Amalamal_40+ tabelBersamaProduksi
Thurayyathurayya_40+ tabelBersamaProduksi
Qaisqais_35+ tabelBersamaBeta
KidElitekidelite_40+ tabelBersamaProduksi
Alphazed Schoolschool_50+ tabelBersamaBeta
Alphazed Montessorimontessori_45+ tabelBersamaInternal

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.

Artikel Terkait