Files
2nd/10_Wiki/Topics/Coding/DB_Serverless_Edge.md
T
2026-05-09 21:08:02 +09:00

302 lines
7.3 KiB
Markdown

---
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]]