--- id: db-serverless-edge title: Serverless / Edge DB β€” Neon / Turso / D1 / Hyperdrive category: Coding status: draft source_trust_level: B verification_status: conceptual created_at: 2026-05-09 updated_at: 2026-05-09 tags: [database, serverless, edge, vibe-coding] tech_stack: { language: "TS", applicable_to: ["Backend"] } applied_in: [] aliases: [Neon, Turso, Cloudflare D1, Hyperdrive, libSQL, edge SQLite, branching DB] --- # Serverless / Edge DB > Lambda / Edge function = connection pool 어렀움. **Neon (Postgres HTTP), Turso (libSQL), Cloudflare D1, Hyperdrive (PG proxy)**. Branching, scale-to-zero, low latency. ## πŸ“– 핡심 κ°œλ… - HTTP-based: connection μ—†μŒ β€” REST 같이. - Branching: production data β†’ dev branch. - Scale-to-zero: μ•ˆ μ“°λ©΄ stop. - Edge: μ‚¬μš©μž κ°€κΉŒμ΄. ## πŸ’» μ½”λ“œ νŒ¨ν„΄ ### Neon (Postgres serverless) ```ts import { neon } from '@neondatabase/serverless'; const sql = neon(process.env.DATABASE_URL!); // HTTP API β€” connection μ—†μŒ const users = await sql`SELECT * FROM users WHERE id = ${userId}`; const user = users[0]; ``` ```ts // λ˜λŠ” Pool (Edge runtime) import { Pool } from '@neondatabase/serverless'; const pool = new Pool({ connectionString: process.env.DATABASE_URL }); const r = await pool.query('SELECT * FROM users WHERE id = $1', [id]); ``` β†’ Standard Postgres + HTTP transport. ### Neon branching (development) ```bash # Branch 생성 neon branches create --name dev-feature-x --parent main # Schema migration test DATABASE_URL=$(neon connection-string dev-feature-x) yarn migrate:up # Production 영ν–₯ μ—†μŒ # Done β†’ branch delete ``` β†’ Git-like database. ### Turso (libSQL = SQLite fork) ```ts import { createClient } from '@libsql/client'; const turso = createClient({ url: 'libsql://my-db.turso.io', authToken: process.env.TURSO_TOKEN, }); const r = await turso.execute({ sql: 'SELECT * FROM users WHERE id = ?', args: [userId], }); console.log(r.rows); ``` β†’ SQLite + replication + edge. ### Turso embedded replica (zero-latency read) ```ts const turso = createClient({ url: 'file:local.db', syncUrl: 'libsql://my-db.turso.io', authToken, syncInterval: 60, // 60s sync }); await turso.sync(); // Read = local file (0 ms) const r = await turso.execute('SELECT * FROM users'); ``` β†’ Read = local, write = remote, μžλ™ sync. ### Cloudflare D1 ```ts // wrangler.toml [[d1_databases]] binding = "DB" database_name = "my-app" database_id = "..." ``` ```ts // Worker export default { async fetch(req: Request, env: Env) { const r = await env.DB.prepare('SELECT * FROM users WHERE id = ?').bind(userId).first(); return Response.json(r); }, }; ``` β†’ SQLite + κΈ€λ‘œλ²Œ read replica. ### Hyperdrive (CF, Postgres / MySQL accelerator) ```ts // wrangler.toml [[hyperdrive]] binding = "HYPERDRIVE" id = "..." # PG / MySQL connection ``` ```ts import postgres from 'postgres'; export default { async fetch(req: Request, env: Env) { const sql = postgres(env.HYPERDRIVE.connectionString); const r = await sql`SELECT * FROM users WHERE id = ${id}`; return Response.json(r); }, }; ``` β†’ Hyperdrive κ°€ connection pool + cache. CF Worker μ•ˆ 일반 PG client. ### PlanetScale (MySQL serverless) ```ts import { Client } from '@planetscale/database'; const client = new Client({ url: process.env.DATABASE_URL, }); const conn = client.connection(); const r = await conn.execute('SELECT * FROM users WHERE id = ?', [id]); ``` β†’ MySQL HTTP. Branching 같이. ### Branching workflow (Neon / PlanetScale) ```yaml # .github/workflows/preview.yml - name: Create branch for PR run: neon branches create --name pr-${{ github.event.number }} --parent main - name: Run migrations run: DATABASE_URL=$BRANCH_URL yarn migrate:up - name: Deploy preview run: vercel deploy --env DATABASE_URL=$BRANCH_URL - name: On PR close β€” delete run: neon branches delete pr-${{ github.event.number }} ``` β†’ λ§€ PR = 자체 DB. ### Scale-to-zero ``` Neon: μ•ˆ μ“°λ©΄ compute stop. λ‹€μŒ query κ°€ cold start (~500ms). Turso: 항상 ν™œμ„± (μž‘μ€ λΉ„μš©). D1: ν™œμ„±. Hyperdrive: pool + cache. ``` β†’ Low-traffic μ•± = Neon κ°€ cheap. ### Cost (λŒ€λž΅) ``` Neon: Free tier β€” 0.5GB / 1 project. Paid $19/month. Turso: Free 9GB / 500 DBs. Paid scaled. D1: Free 5GB / 25M reads/day. Paid pennies/M. Hyperdrive: CF Workers paid. PlanetScale: Free tier β€” but 2024 가격 λ³€κ²½. ``` ### μ‚¬μš©μž 관점 latency ``` 일반 RDS (us-east-1) + Lambda (us-east-1): ~5-20ms query Neon HTTP + Lambda: ~10-30ms Turso embedded replica: ~0ms read D1 (CF worker, edge): ~1-5ms (local region) Hyperdrive (CF worker β†’ cached): ~1-5ms cached ``` ### Drizzle 톡합 ```ts import { drizzle } from 'drizzle-orm/neon-http'; import { neon } from '@neondatabase/serverless'; const sql = neon(process.env.DATABASE_URL!); const db = drizzle(sql); const users = await db.select().from(usersTable).where(eq(usersTable.id, id)); ``` ```ts // Turso import { drizzle } from 'drizzle-orm/libsql'; import { createClient } from '@libsql/client'; const client = createClient({ url, authToken }); const db = drizzle(client); ``` ### Prisma (ꡬ식 β€” Edge 어렀움) ```ts // Prisma 의 Data Proxy / Accelerate ν•„μš” // λ˜λŠ” driver adapter (Neon) import { PrismaClient } from '@prisma/client'; import { PrismaNeon } from '@prisma/adapter-neon'; import { neon } from '@neondatabase/serverless'; const sql = neon(process.env.DATABASE_URL!); const adapter = new PrismaNeon(sql); const prisma = new PrismaClient({ adapter }); ``` ### Vector search (Neon pgvector / Turso SQLite vss) ```sql -- Neon = pgvector κ·ΈλŒ€λ‘œ CREATE EXTENSION vector; CREATE TABLE docs (... embedding VECTOR(1536)); -- Turso = sqlite-vss extension ``` ### Migration tools ```bash # Neon β€” branch 둜 neon branches create --name migration-test DATABASE_URL=$BRANCH yarn migrate:up # Verify neon branches delete migration-test # λ˜λŠ” atlas / drizzle-kit / prisma migrate ``` ### λ™μ‹œμ„± / write ``` Neon: 읽기 닀쀑 (read replica) / write 단일. Turso: read 닀쀑 / write ν•œ κ³³ (primary). D1: write ν•œ region / read κΈ€λ‘œλ²Œ. β†’ λΆ„μ‚° write = λ‹€λ₯Έ system ν•„μš”. ``` ### 단점 ``` Neon: PG ν˜Έν™˜ β€” but 일뢀 extension μ œμ•½. Turso: SQLite κ°€ OLTP 만. analytic X. D1: SQLite κ°™μŒ + 일뢀 extension X. Hyperdrive: 자체 DB X β€” κΈ°μ‘΄ PG κ°€κΉŒμ΄. PlanetScale: FK μ œμ•½ (online schema change μœ„ν•΄). ``` ## πŸ€” μ˜μ‚¬κ²°μ • κΈ°μ€€ | 상황 | μΆ”μ²œ | |---|---| | Vercel + μƒˆ ν”„λ‘œμ νŠΈ | Neon | | Cloudflare Workers | D1 / Hyperdrive | | κΈ€λ‘œλ²Œ low-latency read | Turso embedded | | Postgres κΈ°μ‘΄ | Hyperdrive | | MySQL | PlanetScale | | 큰 OLTP | RDS / Aurora (전톡) | | Analytic | DuckDB / ClickHouse | ## ❌ μ•ˆν‹°νŒ¨ν„΄ - **Lambda + 일반 PG 직접**: connection 폭발. HTTP / Hyperdrive. - **Turso κ°€ analytic κ°€μ •**: SQLite. DuckDB. - **Branch 생성 + μžλ™ delete X**: λΉ„μš©. - **Cold start 무관 prod**: latency. Pool / always-on. - **Edge + complex JOIN**: cross-region λΉ„μ‹Έ. - **Prepared statement cache 무**: 맀번 parse. ## πŸ€– LLM ν™œμš© 힌트 - Vercel / Next = Neon λ””ν΄νŠΈ. - CF Workers = D1 / Hyperdrive. - Local-first = Turso embedded. - Branching = git-like dev. ## πŸ”— κ΄€λ ¨ λ¬Έμ„œ - [[Backend_Connection_Handling]] - [[Backend_Geo_Replication]] - [[DB_Distributed_SQL]]