Cloudflare Workers + D1 实战:边缘数据库全栈应用
Cloudflare Workers + D1 + R2 + Vectorize 是 2026 年最强边缘全栈组合:冷启动 < 5ms / 全球 300+ 节点 / 内置数据库 / 向量搜索。本文从入门到生产级 SaaS。
今日技术简讯
📰 技术简讯 · 2026-07-26
今日聚合 6 条热门技术内容(中文素材优先)。
🤖 AI / LLM
1. Cloudflare Workers AI 推出 DeepSeek-V3
- 链接:https://blog.cloudflare.com/workers-ai-deepseek-v3
- 来源:Cloudflare
- 摘要:Cloudflare Workers AI 推出 DeepSeek-V3 推理,120 亿参数,免费 10K tokens/天。
2. Vectorize GA + Workers AI RAG
- 链接:https://blog.cloudflare.com/vectorize-ga
- 来源:Cloudflare
- 摘要:Vectorize 正式 GA,与 Workers AI 集成,一键 RAG 应用。
🎨 前端 / Web
3. Astro 6 推出 Cloudflare 适配
- 链接:https://astro.build/blog/6
- 来源:Astro
- 摘要:Astro 6 推出 Cloudflare 适配,SSR + 边缘 KV + D1 一键部署。
⚙️ 后端 / 架构
4. D1 推出 Read Replication
- 链接:https://blog.cloudflare.com/d1-read-replication
- 来源:Cloudflare
- 摘要:Cloudflare D1 推出 Read Replication,读延迟 -60%,全球只读副本。
5. R2 + Workers 推出事件流
- 链接:https://blog.cloudflare.com/r2-event-streams
- 来源:Cloudflare
- 摘要:R2 + Workers 推出事件流,文件上传触发 Worker,实时处理。
🚀 独立开发 / OPC
6. 即刻"边缘数据库"专题
- 链接:https://m.okjike.com/edge-db-2026
- 来源:即刻
- 摘要:即刻推出边缘数据库专题,D1 / Turso / Neon Serverless 实战对比。
数据来源:掘金 / InfoQ 中文 / 即刻 / 少数派 / HN 采集时间:2026-07-26 09:00 (UTC+8)
今日深度文
Cloudflare Workers + D1 实战:边缘数据库全栈应用
一句话结论:Cloudflare Workers + D1 = 现代边缘全栈。冷启动 < 5ms / 全球 300+ 节点 / SQLite 兼容 / 无服务器费用。本文从入门到生产级 SaaS,含 5 个实战项目。
背景
Cloudflare 生态在 2026 年已完整:
- Workers:边缘函数(V8 Isolates)
- D1:边缘 SQLite(兼容 Prisma / Drizzle)
- R2:S3 兼容对象存储
- Vectorize:边缘向量数据库
- KV:低延迟 KV 存储
- Workers AI:边缘 AI 推理
"Workers + D1"组合 = 完整全栈:
- 无服务器费用(按请求付费)
- 全球 300+ 节点
- 冷启动 < 5ms
- 内置数据库 / 存储 / AI / 向量搜索
6 大核心优势
1. 极致冷启动
// 冷启动对比
Node.js: 200ms
Deno: 5ms
Cloudflare Workers: < 5ms
Workers 用 V8 Isolates(轻量沙箱),无容器开销。
2. 全球部署
一次部署,全球 300+ 节点
美西 → 用户 50ms
欧洲 → 用户 30ms
亚洲 → 用户 20ms
3. 内置完整生态
| 服务 | 用途 | 价格 |
|---|---|---|
| Workers | 边缘函数 | 免费 100K/天 |
| D1 | SQLite 数据库 | 免费 5GB |
| R2 | 对象存储 | 免费 10GB |
| KV | 低延迟 KV | 免费 100K 读/天 |
| Vectorize | 向量搜索 | 免费 5M 维度 |
| Workers AI | AI 推理 | 免费 10K tokens/天 |
4. 强大工具链
# Wrangler CLI
$ npm install -g wrangler
$ wrangler init my-app
$ wrangler dev # 本地开发
$ wrangler deploy # 部署
$ wrangler d1 create # 创建数据库
$ wrangler d1 execute # 执行 SQL
$ wrangler tail # 实时日志
5. 完整 TypeScript 支持
// wrangler.toml
name = "my-app"
main = "src/index.ts"
compatibility_date = "2026-07-01"
[[d1_databases]]
binding = "DB"
database_name = "my-db"
database_id = "xxx"
[[r2_buckets]]
binding = "STORAGE"
bucket_name = "my-bucket"
[[vectorize]]
binding = "VECTORIZE"
index_name = "my-index"
6. 多种部署方式
# 直接部署
$ wrangler deploy
# GitHub Actions 自动部署
# .github/workflows/deploy.yml
# Pages 部署
$ wrangler pages deploy ./dist
D1 实战
创建数据库
# 创建 D1
$ wrangler d1 create my-db
# 创建成功后会输出 database_id
# 配置 wrangler.toml
[[d1_databases]]
binding = "DB"
database_name = "my-db"
database_id = "xxx"
迁移
# 本地迁移
$ wrangler d1 execute my-db --local --file=./schema.sql
# 远程迁移
$ wrangler d1 execute my-db --remote --file=./schema.sql
schema.sql
CREATE TABLE users (
id TEXT PRIMARY KEY,
email TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
created_at INTEGER NOT NULL DEFAULT (unixepoch())
);
CREATE TABLE posts (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
title TEXT NOT NULL,
content TEXT NOT NULL,
published INTEGER NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT (unixepoch()),
FOREIGN KEY (user_id) REFERENCES users(id)
);
CREATE INDEX idx_posts_user_id ON posts(user_id);
CREATE INDEX idx_posts_created_at ON posts(created_at DESC);
CRUD API
// src/index.ts
export interface Env {
DB: D1Database;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
// CORS
if (request.method === 'OPTIONS') {
return new Response(null, {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE',
'Access-Control-Allow-Headers': 'Content-Type',
},
});
}
// 列表
if (url.pathname === '/api/posts' && request.method === 'GET') {
const { results } = await env.DB.prepare(
'SELECT * FROM posts WHERE published = ? ORDER BY created_at DESC LIMIT 20'
).bind(1).all();
return Response.json(results);
}
// 创建
if (url.pathname === '/api/posts' && request.method === 'POST') {
const { title, content, userId } = await request.json();
const id = crypto.randomUUID();
await env.DB.prepare(
'INSERT INTO posts (id, user_id, title, content) VALUES (?, ?, ?, ?)'
).bind(id, userId, title, content).run();
return Response.json({ id }, { status: 201 });
}
// 详情
if (url.pathname.startsWith('/api/posts/') && request.method === 'GET') {
const id = url.pathname.split('/').pop();
const post = await env.DB.prepare(
'SELECT * FROM posts WHERE id = ?'
).bind(id).first();
if (!post) return new Response('Not found', { status: 404 });
return Response.json(post);
}
return new Response('Not found', { status: 404 });
},
};
使用 Drizzle(类型安全)
// src/db.ts
import { drizzle } from 'drizzle-orm/d1';
import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core';
import { eq, desc } from 'drizzle-orm';
export const users = sqliteTable('users', {
id: text('id').primaryKey(),
email: text('email').notNull().unique(),
name: text('name').notNull(),
createdAt: integer('created_at').notNull(),
});
export const posts = sqliteTable('posts', {
id: text('id').primaryKey(),
userId: text('user_id').notNull(),
title: text('title').notNull(),
content: text('content').notNull(),
published: integer('published').notNull().default(0),
createdAt: integer('created_at').notNull(),
});
export function getDb(d1: D1Database) {
return drizzle(d1, { schema: { users, posts } });
}
// src/api.ts
import { getDb, posts } from './db';
export default {
async fetch(request: Request, env: Env) {
const db = getDb(env.DB);
const list = await db.select().from(posts)
.where(eq(posts.published, 1))
.orderBy(desc(posts.createdAt))
.limit(20);
return Response.json(list);
},
};
4 个实战项目
项目 1:博客系统
export default {
async fetch(request: Request, env: Env) {
const url = new URL(request.url);
if (url.pathname === '/api/posts' && request.method === 'GET') {
const { results } = await env.DB.prepare(`
SELECT p.*, u.name as author_name
FROM posts p
JOIN users u ON p.user_id = u.id
WHERE p.published = 1
ORDER BY p.created_at DESC
LIMIT 20
`).all();
return Response.json(results);
}
// ...
},
};
项目 2:短链服务
export default {
async fetch(request: Request, env: Env) {
const url = new URL(request.url);
// 创建短链
if (url.pathname === '/api/shorten' && request.method === 'POST') {
const { target } = await request.json();
const code = Math.random().toString(36).slice(2, 8);
await env.DB.prepare(
'INSERT INTO short_links (code, target, created_at) VALUES (?, ?, ?)'
).bind(code, target, Date.now()).run();
return Response.json({ code, short: `${url.origin}/${code}` });
}
// 访问短链
const code = url.pathname.slice(1);
if (code && code !== 'api') {
const link = await env.DB.prepare(
'SELECT target FROM short_links WHERE code = ?'
).bind(code).first();
if (link) {
// 统计点击
await env.DB.prepare(
'UPDATE short_links SET clicks = clicks + 1 WHERE code = ?'
).bind(code).run();
return Response.redirect(link.target as string, 302);
}
}
return new Response('Not found', { status: 404 });
},
};
项目 3:RAG 应用(与 7/15 关联)
export interface Env {
DB: D1Database;
VECTORIZE: VectorizeIndex;
AI: Ai;
}
export default {
async fetch(request: Request, env: Env) {
const url = new URL(request.url);
// 上传文档
if (url.pathname === '/api/documents' && request.method === 'POST') {
const { title, content } = await request.json();
const id = crypto.randomUUID();
// 生成 embedding(Workers AI)
const { response } = await env.AI.run(
'@cf/baai/bge-base-en-v1.5',
{ text: content }
) as { response: number[] };
// 存 D1
await env.DB.prepare(
'INSERT INTO documents (id, title, content) VALUES (?, ?, ?)'
).bind(id, title, content).run();
// 存 Vectorize
await env.VECTORIZE.upsert([{
id,
values: response,
metadata: { title },
}]);
return Response.json({ id });
}
// 搜索
if (url.pathname === '/api/search' && request.method === 'POST') {
const { query } = await request.json();
// Embedding
const { response } = await env.AI.run(
'@cf/baai/bge-base-en-v1.5',
{ text: query }
) as { response: number[] };
// 向量搜索
const results = await env.VECTORIZE.query(response, {
topK: 5,
returnMetadata: 'all',
});
return Response.json(results);
}
return new Response('Not found', { status: 404 });
},
};
项目 4:R2 文件上传
export interface Env {
STORAGE: R2Bucket;
}
export default {
async fetch(request: Request, env: Env) {
const url = new URL(request.url);
// 上传
if (url.pathname === '/api/upload' && request.method === 'POST') {
const formData = await request.formData();
const file = formData.get('file') as File;
const key = `${Date.now()}-${file.name}`;
await env.STORAGE.put(key, file.stream(), {
httpMetadata: { contentType: file.type },
customMetadata: { uploadedBy: 'anonymous' },
});
return Response.json({ key, url: `/api/files/${key}` });
}
// 下载
if (url.pathname.startsWith('/api/files/')) {
const key = url.pathname.split('/').pop()!;
const object = await env.STORAGE.get(key);
if (!object) return new Response('Not found', { status: 404 });
return new Response(object.body, {
headers: {
'content-type': object.httpMetadata?.contentType || 'application/octet-stream',
'cache-control': 'public, max-age=31536000',
},
});
}
return new Response('Not found', { status: 404 });
},
};
5 个常见坑
坑 1:D1 单数据库限制
// ❌ 单数据库最大 10GB
// 解决方案:分库 / 归档旧数据
// ❌ 写延迟 100ms(vs PostgreSQL 10ms)
// 解决方案:用 KV 缓存热点数据
坑 2:CPU 时间限制
Workers 免费版:10ms CPU 时间
Workers 付费版:50ms(默认)/ 30s(最长)
❌ 同步长任务
✅ 异步 + 后台任务(Queues / Cron Triggers)
坑 3:本地开发差异
// ❌ 有些 API 本地不支持
// --local 模式 vs --remote 模式
// ✅ 部署前用 --remote 测试
$ wrangler dev --remote
坑 4:冷启动数据库连接
// ❌ 每次请求都创建连接
const conn = new Connection();
✅ D1 自动管理连接(每次请求一个新连接)
坑 5:状态不能跨请求
// ❌ 用全局变量缓存
let cache = {}; // ❌ Worker 可能被销毁
// ✅ 用 D1 / KV / R2 / Vectorize
await env.KV.get('key');
与之前内容的关系
7/17 Rust + Axum → 后端框架
7/18 Vercel + Cloudflare → 部署(含 CF)
7/19 Docker → 容器化
7/21 PostgreSQL → 数据库
7/25 Deno 2 + Hono → 运行时
7/26 Workers + D1 → 边缘全栈 ← 今天
→ "框架 → 部署 → 数据库 → 运行时 → 边缘"
7 天落地路径
Day 1:注册 Cloudflare
- 注册账号
- 安装 wrangler
- wrangler login
Day 2:第一个 Worker
$ wrangler init my-app
$ cd my-app
$ wrangler dev
Day 3:D1 数据库
$ wrangler d1 create my-db
# 配置 wrangler.toml
$ wrangler d1 execute my-db --local --file=./schema.sql
Day 4:CRUD API
// 列表 / 详情 / 创建 / 更新 / 删除
Day 5:前端集成
// React / Vue / Astro
Day 6:高级功能
// R2 文件 / Vectorize 向量搜索 / Workers AI
Day 7:部署 + 监控
$ wrangler deploy
$ wrangler tail # 实时日志
我的看法
Cloudflare Workers + D1 是 2026 年独立开发者的"瑞士军刀":
- 零服务器费用:免费额度足够个人项目
- 极致性能:全球 300+ 节点 / 冷启动 < 5ms
- 完整生态:DB / Storage / AI / Vector / KV
- 简单部署:
wrangler deploy一行命令 - 类型安全:完整 TypeScript
对独立开发者的建议:
- 小项目首选:博客 / Landing Page / SaaS MVP
- 中等项目:完整全栈应用
- 大项目:搭配专用数据库(Neon / Supabase)
参考
- Cloudflare Workers
- D1 文档
- Vectorize
- Workers AI
- R2 文档
- Wrangler CLI
- Vercel + Cloudflare(7/18)
- PostgreSQL(7/21)
- Deno + Hono(7/25)
本文基于 Cloudflare Workers 2026 年 7 月最新版本。
📚 同主题文章
Deno 2 + Hono 实战:现代边缘运行时全栈开发
Deno 2 + Hono 是 2026 年最强的边缘运行时组合:原生 TypeScript、内置工具链、冷启动 < 5ms。本文从入门到生产,含 4 个实战项目 + 性能对比 + 迁移指南。
Vercel + Cloudflare 双部署实战:全球 50ms 延迟
Vercel 是 Next.js 最佳部署平台,Cloudflare 是全球 CDN 之王。两者组合实现"全球 P50 < 50ms"。本文含完整双部署流程 + 4 个实战项目 + 性能对比。
Bun 全栈实战:从 Node.js 迁移完整指南
Bun 1.4 已成熟,速度比 Node.js 快 3-5 倍。本文演示从 Node.js 迁移到 Bun 的完整步骤和实战经验。