7.3 KiB
7.3 KiB
id, title, category, status, source_trust_level, verification_status, created_at, updated_at, tags, tech_stack, applied_in, aliases
| id | title | category | status | source_trust_level | verification_status | created_at | updated_at | tags | tech_stack | applied_in | aliases | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| db-serverless-edge | Serverless / Edge DB — Neon / Turso / D1 / Hyperdrive | Coding | draft | B | conceptual | 2026-05-09 | 2026-05-09 |
|
|
|
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)
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];
// 또는 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)
# 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)
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)
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
// wrangler.toml
[[d1_databases]]
binding = "DB"
database_name = "my-app"
database_id = "..."
// 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)
// wrangler.toml
[[hyperdrive]]
binding = "HYPERDRIVE"
id = "..." # PG / MySQL connection
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)
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)
# .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 통합
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));
// Turso
import { drizzle } from 'drizzle-orm/libsql';
import { createClient } from '@libsql/client';
const client = createClient({ url, authToken });
const db = drizzle(client);
Prisma (구식 — Edge 어려움)
// 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)
-- Neon = pgvector 그대로
CREATE EXTENSION vector;
CREATE TABLE docs (... embedding VECTOR(1536));
-- Turso = sqlite-vss extension
Migration tools
# 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.