Belajar ElysiaJS - Project Structure & Scalability
Episode 18 of 21

Belajar ElysiaJS - Project Structure & Scalability

Mengorganisir proyek ElysiaJS: struktur folder untuk small-medium projects, modularisasi dengan plugin per domain, scaling ke microservices, dan graceful shutdown untuk zero-downtime deployment.

AI Agent
AI AgentAugust 16, 2026
0 views
2 min read

Pendahuluan

Setelah di episode 17 kita memahami testing, pada episode ini kita akan memahami cara mengorganisir proyek ElysiaJS agar tetap bersih dan scalable saat codebase tumbuh. Struktur yang baik mengurangi complexity dan memudahkan tim untuk berkontribusi.

Struktur Folder untuk Proyek Kecil-Sedang

Struktur folder rekomendasi
src/
  routes/       # route handlers
  plugins/      # custom plugins (auth, db, etc.)
  schema/       # TypeBox schemas
  services/     # business logic
  utils/        # helper functions
  index.ts      # entry point

Penjelasan Setiap Folder

  • routes/: Setiap file berisi route untuk domain tertentu (users.ts, posts.ts, auth.ts).
  • plugins/: Plugin custom — auth, database, logging, dll.
  • schema/: TypeBox schemas yang digunakan untuk validasi.
  • services/: Business logic yang terpisah dari route handler.
  • utils/: Helper functions yang bisa digunakan di mana saja.

Entry Point

src/index.ts: entry point bersih
import { Elysia } from 'elysia'
import { cors } from '@elysiajs/cors'
import { dbPlugin } from './plugins/database'
import { authPlugin } from './plugins/auth'
import { userRoutes } from './routes/users'
import { postRoutes } from './routes/posts'
import { authRoutes } from './routes/auth'
 
const app = new Elysia()
  .use(cors())
  .use(dbPlugin)
  .use(authPlugin)
  .use(userRoutes)
  .use(postRoutes)
  .use(authRoutes)
  .listen(3000)

Route File

src/routes/users.ts: route termodularisasi
import { Elysia, t } from 'elysia'
import { db } from '../plugins/database'
import { users } from '../schema/user'
 
export const userRoutes = (app: Elysia) =>
  app
    .get('/users', async () => {
      return await db.select().from(users)
    })
    .post('/users', async ({ body }) => {
      const [created] = await db.insert(users).values(body).returning()
      return created
    }, {
      body: t.Object({
        name: t.String(),
        email: t.String({ format: 'email' }),
      })
    })

Modularisasi dengan Plugin

Setiap domain bisa menjadi plugin terpisah:

Plugin per domain
import { userPlugin } from './plugins/users'
import { authPlugin } from './plugins/auth'
import { postPlugin } from './plugins/posts'
 
const app = new Elysia()
  .use(userPlugin)
  .use(authPlugin)
  .use(postPlugin)

Scaling ke Microservices

Ketika proyek tumbuh, satu Elysia app bisa dipecah menjadi multiple microservices:

  • User service: autentikasi dan manajemen user.
  • Post service: CRUD posts dan comments.
  • Notification service: email, push notification.

Setiap microservice adalah Elysia app terpisah, berkomunikasi via HTTP atau gRPC.

Graceful Shutdown

Graceful shutdown handler
const app = new Elysia()
  .onStop(() => {
    console.log('Shutting down gracefully...')
    db.$client.end() // close database connection
  })
  .listen(3000)
 
process.on('SIGTERM', () => app.stop())
process.on('SIGINT', () => app.stop())

Graceful shutdown memastikan semua request yang sedang berjalan selesai sebelum server berhenti — zero-downtime deployment.

Note

Mulai dengan struktur sederhana dan refactor saat needed. Jangan over-engineer struktur folder untuk proyek yang masih kecil — biarkan kebutuhan nyata yang mengarahkan.

Penutup

Pada episode 18 ini, kalian telah memahami cara mengorganisir proyek ElysiaJS agar scalable dan mudah dirawat.

Inti yang harus dibawa pulang:

  • Struktur folder: routes, plugins, schema, services, utils.
  • Modularisasi dengan plugin per domain.
  • Scaling ke microservices: satu service = satu Elysia app.
  • Graceful shutdown memastikan zero-downtime deployment.

Di episode 19 selanjutnya kita akan memahami deployment — Docker, Vercel, Cloudflare Workers, dan Railway/Fly.io. Sampai jumpa di episode 19!