Skip to main content

01 — Tech Stack

Dokumen ini menjelaskan semua teknologi yang digunakan untuk membangun backend ELJoy, lengkap dengan alasan pemilihan dan peran masing-masing.


Ringkasan Stack​

┌─────────────────────────────────────────────────────────────┐
│ CLIENT (Frontend) │
│ React 19 + Vite + TypeScript │
└────────────────────────┬────────────────────────────────────┘
│ HTTPS / SSE
▼
┌─────────────────────────────────────────────────────────────┐
│ API GATEWAY / CDN │
│ Cloudflare (Proxy) │
└────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ APPLICATION SERVER │
│ Hono.js + Node.js + TypeScript │
├─────────────┬───────────────┬───────────────┬───────────────┤
│ Drizzle │ Better Auth │ Vercel AI │ BullMQ │
│ ORM │ │ SDK │ (Queue) │
└──────┬──────┴───────┬───────┴───────┬───────┴───────┬───────┘
│ │ │ │
▼ ▼ ▼ ▼
┌──────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────┐
│PostgreSQL│ │ Redis/Upstash│ │ OpenAI / │ │ Cloud │
│ │ │ │ │ Google AI │ │ Storage │
│(Neon/ │ │(Cache, │ │ │ │ (R2/S3) │
│ Supabase)│ │ Session, │ │ Deepgram │ │ │
│ │ │ Rate Limit) │ │ (STT/TTS) │ │ │
└──────────┘ └──────────────┘ └──────────────┘ └──────────┘

Detail Per Layer​

1. Runtime & Bahasa​

TeknologiVersiPeran
Node.jsv22 LTSRuntime server. Dipilih karena satu bahasa dengan frontend (TypeScript), ecosystem NPM terbesar, dan performa async I/O yang sangat baik untuk aplikasi real-time.
TypeScript5.xType safety end-to-end. Mengurangi bug runtime, meningkatkan DX (Developer Experience), dan memudahkan kolaborasi tim.

Kenapa Node.js, bukan Go/Python/Java?

  • Satu bahasa (TypeScript) untuk FE dan BE → tim lebih efisien
  • Ecosystem library untuk AI, audio, dan real-time sudah sangat matang
  • Non-blocking I/O cocok untuk SSE streaming dan concurrent voice sessions
  • Startup time cepat, memory footprint ringan untuk deployment cloud

2. Web Framework​

TeknologiVersiPeran
Hono.js4.xFramework web utama. Ultra-ringan (~14KB), TypeScript-first, multi-runtime (Node.js, Bun, Cloudflare Workers, Deno).

Kenapa Hono, bukan Express/Fastify/NestJS?

KriteriaExpressFastifyNestJSHono ✅
Ukuran bundle~200KB~100KB~2MB+~14KB
TypeScript native❌ (perlu setup)⚠️ (partial)✅✅
PerformanceLambatCepatMediumSangat cepat
Learning curveRendahRendahTinggiRendah
Edge-ready❌❌❌✅
Middleware ecosystemSangat banyakBanyakBuilt-inBanyak

Fitur Hono yang kita pakai:

  • Built-in middleware: CORS, JWT verification, rate limiting
  • hono/streaming — SSE streaming untuk AI response
  • hono/validator — Request validation dengan Zod
  • RPC client — Type-safe API client yang bisa di-share ke frontend
  • Multi-runtime — Bisa deploy ke VPS, serverless, atau edge

3. Database​

TeknologiVersiPeran
PostgreSQL16+Database utama (relational). Menyimpan semua data terstruktur: user, assessment, learning journey, content, membership.
Drizzle ORM0.35+ORM TypeScript yang type-safe, SQL-like syntax, zero overhead, dan migration bawaan.

Kenapa PostgreSQL?

  • JSONB support — Cocok untuk menyimpan data semi-terstruktur (AI evaluation results, learner profile metrics)
  • Full-text search — Pencarian konten tanpa perlu Elasticsearch di awal
  • Array & Enum types — Efisien untuk tags, CEFR levels, mode types
  • Reliable & mature — Battle-tested, excellent tooling
  • Managed options — Neon, Supabase, atau Railway menyediakan PostgreSQL gratis/murah untuk MVP

Kenapa Drizzle, bukan Prisma?

KriteriaPrismaDrizzle ✅
Bundle size~10MB+~100KB
Query styleCustom DSLSQL-like
Type safety✅✅
PerformanceOverhead (engine)Zero overhead
MigrationGenerate dari schemaGenerate dari schema
Raw SQLSulitMudah
Learning curveSedangRendah (kalau tahu SQL)

4. Cache & Session​

TeknologiVersiPeran
Redis7.xIn-memory data store untuk caching, session management, rate limiting, dan pub/sub.
Upstash RedisManagedRedis serverless — bayar per request, cocok untuk MVP/startup.

Apa yang disimpan di Redis:

  • Session tokens — Login session user (TTL 7 hari)
  • Rate limit counters — Pencegahan abuse API (per IP / per user)
  • AI context cache — Konteks percakapan terakhir user (TTL 30 menit)
  • Leaderboard / streak data — Sorted sets untuk ranking harian
  • Real-time state — Status mic, status companion, assessment progress

5. Authentication​

TeknologiVersiPeran
Better Auth1.xLibrary autentikasi TypeScript-native, self-hosted, framework-agnostic.

Kenapa Better Auth, bukan Clerk/Auth0/NextAuth?

  • Self-hosted — Data user tetap di database kita sendiri, tidak tergantung vendor
  • TypeScript-first — Type-safe API, auto-complete yang bagus
  • Framework-agnostic — Bisa dipasang di Hono, Express, atau apapun
  • Built-in features: Email/password, OAuth (Google, Apple), magic link, session management, 2FA
  • Database adapter — Langsung pakai Drizzle adapter, data tersimpan di PostgreSQL kita
  • Gratis — Open source, tidak ada biaya per-user

Auth Methods yang akan digunakan:

  1. Email + Password — Registrasi standar
  2. Google OAuth — Login cepat via Google
  3. Apple Sign-In — Untuk user iOS (wajib di App Store)
  4. Magic Link — Password-less via email (opsional)

6. AI Services​

TeknologiVersiPeran
Vercel AI SDK4.xUnified interface untuk memanggil berbagai AI provider (OpenAI, Google AI, Anthropic). Mendukung streaming, tool calling, dan structured output.
OpenAI GPT-4o-miniLatestLLM utama untuk AI Companion — percakapan, evaluasi, feedback. Cost-effective dengan kualitas tinggi.
Google Gemini 2.0 FlashLatestLLM alternatif / fallback. Digunakan untuk assessment evaluation dan content generation.
DeepgramNova-2Speech-to-Text (STT) — Akurasi tinggi, latensi rendah, harga terjangkau.
OpenAI TTStts-1 / tts-1-hdText-to-Speech — Suara natural untuk AI Companion berbicara.

Kenapa Vercel AI SDK?

  • Provider-agnostic — Ganti dari OpenAI ke Gemini tanpa ubah kode
  • Streaming built-in — streamText() langsung jadi SSE
  • Structured output — Parse JSON dari LLM dengan Zod schema validation
  • Tool calling — AI bisa memanggil fungsi (cek progress user, ambil konten)
  • Telemetry — Log usage, latency, token count otomatis

7. Background Jobs & Queue​

TeknologiVersiPeran
BullMQ5.xJob queue berbasis Redis untuk background processing.

Job yang diproses di background:

  • 🎤 Audio Processing — Konversi format audio user sebelum dikirim ke STT
  • 🤖 AI Evaluation — Analisis pronunciation, grammar, fluency (bisa lambat, jangan blocking)
  • 📊 Progress Calculation — Update learner profile, recalculate CEFR level
  • 📧 Email Notifications — Kirim email verifikasi, reminder belajar
  • 🧹 Cleanup Jobs — Hapus temporary audio files, expired sessions

8. File Storage​

TeknologiVersiPeran
Cloudflare R2S3-compatibleObject storage untuk file audio, gambar konten, dan media assets.

Kenapa Cloudflare R2, bukan AWS S3?

  • Zero egress fee — Tidak bayar saat user download/stream audio (S3 mahal untuk ini)
  • S3-compatible API — Library yang sama, tinggal ganti endpoint
  • Global CDN — File otomatis ter-cache di edge Cloudflare
  • Murah — 10GB gratis, setelahnya ~$0.015/GB/bulan

File yang disimpan:

  • Audio recording user (PCM → MP3/OGG)
  • Audio TTS dari AI Companion
  • Gambar untuk Picture Description mode
  • Profile picture user
  • Content media (gambar, icon topik)

9. Validation & Schema​

TeknologiVersiPeran
Zod3.xRuntime validation & TypeScript schema definition. Dipakai di request body validation, environment variables, AI structured output, dan database schema.

Contoh penggunaan:

// Request validation
const CreateUserSchema = z.object({
email: z.string().email(),
name: z.string().min(2).max(100),
nativeLanguage: z.enum(['id', 'en']),
});

// AI structured output
const EvaluationSchema = z.object({
overallScore: z.number().min(0).max(100),
pronunciation: z.number().min(0).max(100),
grammar: z.number().min(0).max(100),
fluency: z.number().min(0).max(100),
feedback: z.string(),
corrections: z.array(z.object({
original: z.string(),
corrected: z.string(),
explanation: z.string(),
})),
});

10. Monitoring & Logging​

TeknologiVersiPeran
Pino9.xStructured JSON logger. Super cepat, low overhead.
Better Stack (Logtail)ManagedLog aggregation & search. Free tier cukup untuk MVP.
SentryLatestError tracking & performance monitoring.

11. Testing​

TeknologiVersiPeran
Vitest2.xUnit & integration testing. Sama dengan frontend, konfigurasi shared.
SupertestLatestHTTP endpoint testing. Simulasi request ke Hono routes.
TestcontainersLatestSpin up PostgreSQL & Redis di Docker untuk integration test.

12. Development Tools​

TeknologiPeran
pnpmPackage manager (monorepo-friendly, hemat disk)
TurborepoMonorepo build orchestration (sudah dipakai di project ini)
tsxTypeScript runner untuk development (watch mode)
dotenvEnvironment variable management
BiomeLinter + Formatter (lebih cepat dari ESLint + Prettier)

Ringkasan Dependency​

{
"dependencies": {
"hono": "^4.x",
"@hono/node-server": "^1.x",
"drizzle-orm": "^0.35.x",
"postgres": "^3.x",
"better-auth": "^1.x",
"ai": "^4.x",
"@ai-sdk/openai": "^1.x",
"@ai-sdk/google": "^1.x",
"bullmq": "^5.x",
"ioredis": "^5.x",
"@aws-sdk/client-s3": "^3.x",
"zod": "^3.x",
"pino": "^9.x",
"nanoid": "^5.x",
"dayjs": "^1.x"
},
"devDependencies": {
"typescript": "^5.x",
"tsx": "^4.x",
"vitest": "^2.x",
"drizzle-kit": "^0.25.x",
"@biomejs/biome": "^1.x",
"dotenv": "^16.x"
}
}

Environment Variables​

# === Server ===
NODE_ENV=development
PORT=3001
API_BASE_URL=http://localhost:3001

# === Database ===
DATABASE_URL=postgresql://user:pass@localhost:5432/eljoy

# === Redis ===
REDIS_URL=redis://localhost:6379

# === Auth ===
BETTER_AUTH_SECRET=your-random-secret-min-32-chars
BETTER_AUTH_URL=http://localhost:3001
GOOGLE_CLIENT_ID=xxx
GOOGLE_CLIENT_SECRET=xxx
APPLE_CLIENT_ID=xxx
APPLE_CLIENT_SECRET=xxx

# === AI Services ===
OPENAI_API_KEY=sk-xxx
GOOGLE_GENERATIVE_AI_API_KEY=xxx
DEEPGRAM_API_KEY=xxx

# === Storage ===
R2_ACCOUNT_ID=xxx
R2_ACCESS_KEY_ID=xxx
R2_SECRET_ACCESS_KEY=xxx
R2_BUCKET_NAME=eljoy-media

# === Monitoring ===
SENTRY_DSN=https://xxx@sentry.io/xxx
LOGTAIL_SOURCE_TOKEN=xxx