关于 backend-patterns
backend-patterns 是面向后端开发的技能,帮助根据现有架构选择和实现合适的服务端模式。内容涵盖请求处理、数据库、缓存、后台任务及分布式系统,并强调验证与安全。
主要功能
- 01先检查现有架构与实现
- 02提供 Server Actions 和 tRPC 模式
- 03涵盖数据库、缓存与后台任务
- 04介绍限流和分布式系统模式
- 05验证认证、输入、错误与幂等性
适用场景
- 01为 Next.js Server Actions 设计安全的写入流程
- 02为订单等副作用设置可重试的后台任务
- 03在数据库操作中处理并发更新或软删除
- 04为敏感接口增加限流与输入验证
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ kensaurus/ skills --skill backend-patterns安装后在 Claude Code 中输入/backend-patterns确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/architecture-patterns.mddata-and-jobs.mdrequest-patterns.md详细介绍
后端模式技能
自由度:混合。 应用哪种模式[高自由度];
现有架构探查和验证清单[低自由度 — 按原样执行]。
推理方式
- 观察 — 现有的 server/api/actions、ORM、队列、缓存
- 解读 — 缺少模式、模式重复,还是层级错误
- 分类 — 复用 / 添加队列 / 添加缓存 / 添加速率限制 / 边缘函数
- 确定严重程度 — 未经身份验证的变更优先级高于缺少缓存
示例
观察:
createOrder会在请求中同步发送邮件;没有 Inngest/队列;结账 p95 为 4s。 解读: 确认邮件属于响应后的工作,而非请求路径的一部分。 分类: 使用after()或order/created任务;保持写入操作的事务性。 验证: 订单行成功提交;邮件/库存处理在响应后运行;重试不会导致重复扣款。
报告前自我审查
- 先检查现有实现 — 添加第二种模式前,已搜索 server/api/actions
- 身份验证 + 验证 — 每个变更操作都会检查会话并使用 Zod
- 幂等 — 新路径上的重试不会重复应用操作
- 明确负责人 — 选择哪种架构 →
audit-backend-architecture
使用现代模式和最佳实践,设计可扩展、易维护的后端架构。
代码示例主要使用 Next.js App Router + Supabase/Prisma。这些模式与技术栈无关——请根据检测到的生态系统调整 ORM、客户端库和部署目标。
先检查现有实现 [低自由度 — 按原样执行]
实现任何后端模式之前,请先确认:
- 检查现有架构:
ls -la src/server/ src/api/ app/api/ supabase/functions/ 2>/dev/null
cat package.json | grep -i "prisma\|drizzle\|supabase\|trpc"
- 检查现有模式:
rg "createTRPCRouter|publicProcedure" --type ts -l
rg "'use server'" --type ts -l
ls -la supabase/migrations/*.sql 2>/dev/null | tail -5
- 检查数据库设置:
cat prisma/schema.prisma 2>/dev/null | head -50
cat supabase/config.toml 2>/dev/null
原因: 后端更改影响范围广。请先了解现有架构。
Server Actions(Next.js 16+) [高自由度]
Next.js 16:默认使用 Turbopack;使用 'use cache' + cacheComponents;设置 reactCompiler: true;middleware.ts → proxy.ts(同时 grep 两者)。即时导航 → enhance-web-instant-nav。
- 每个 action 内的顺序:身份验证检查 → Zod
safeParse→ 执行 → 映射已知错误(PrismaP2002)→ 通用失败消息。 - 返回
ActionResult<T>:{ success: true, data }或{ success: false, error, fieldErrors? };绝不向客户端抛出异常。 - 成功写入后调用
revalidatePath。 - 响应后的工作(确认邮件、库存、通知)应放在来自
next/server的after()中,确保写入操作具有事务性。
'use server'
import { after } from 'next/server'
export async function createOrder(formData: FormData) {
const order = await db.order.create({ data: { /* ... */ } })
after(async () => { // runs after the response is sent
await sendOrderConfirmation(order.id)
await updateInventory(order.items)
})
revalidatePath('/orders')
return { success: true, data: order }
}
完整的 createUser action 和 after() 示例:references/request-patterns.md §Server Actions。
tRPC 设置 [高自由度]
- 任何人都可执行的读取操作使用
publicProcedure;任何使用ctx.session的操作都使用protectedProcedure。 - 每个 procedure 都有 Zod
.input();变更操作从会话中设置createdById,而非使用输入值。 - 列表端点使用游标分页:获取
limit + 1条记录,将多出的一条移出并作为nextCursor。
完整的 usersRouter(getById、create、游标分页列表):references/request-patterns.md §tRPC router 定义。
Supabase Edge Functions [高自由度]
- 使用
Deno.serve;首先使用 CORS 标头响应OPTIONS。 - 解析 JSON 前,先根据原始请求体验证 webhook 签名;不匹配时返回
401。 - 来自
SUPABASE_SERVICE_ROLE_KEY的管理客户端会绕过 RLS;只能在函数内部使用。 - 捕获所有异常;在服务端记录日志,并返回带有 CORS 标头的通用
500JSON 响应体。
完整的 process-webhook 函数:references/request-patterns.md §Supabase Edge Function。
数据库模式 [HIGH freedom]
- 乐观锁 — 使用
version INT列;执行UPDATE ... WHERE id = $1 AND version = $2,并将影响 0 行视为发生了并发更新。 - 软删除 — 使用可空的
deletedAt并为其建立索引;每次读取都筛选deletedAt: null;删除时设置时间戳。 - 审计日志 — 通过使用
TG_OP、row_to_json和auth.uid()的SECURITY DEFINER触发器填充audit_logs(table_name, record_id, action, old_data, new_data, user_id)。
UPDATE orders SET status = 'shipped', version = version + 1
WHERE id = $1 AND version = $2; -- 0 rows → concurrent update, retry or surface conflict
Prisma 软删除模型和完整审计触发器:references/data-and-jobs.md §Soft deletes、§Audit logging。
缓存模式 [HIGH freedom]
- Next.js:使用
fetch(url, { next: { revalidate, tags } });按需调用revalidateTag;在数据库查询外层使用带标签的unstable_cache。 - Redis(Upstash):使用一个
getCachedData(key, fetcher, ttl)助手,采用 cache-aside 模式;按实体和 ID 设置键(user:${id})。 - 根据可容忍的数据陈旧程度选择 TTL,并始终添加标签,以便写入操作能够使缓存失效。
const getCachedUser = unstable_cache(
async (id: string) => db.user.findUnique({ where: { id } }),
['user'],
{ revalidate: 3600, tags: ['users'] }
)
Next.js 缓存调用和 Redis 助手:references/data-and-jobs.md §Next.js cache、§Redis caching。
后台任务 [HIGH freedom]
- 默认使用 Inngest。
inngest.createFunction({ id }, { event }, async ({ event, step }) => ...);将每个副作用放在单独的step.run中,这样重试时会从中断处继续,而不是重新开始。 - 写入提交后,通过 Server Action 调用
inngest.send({ name: 'order/created', data })触发任务。 - 提前退出(缺货)应使用
step.run并执行return { status: 'cancelled' },而不是抛出异常。
export const processOrder = inngest.createFunction(
{ id: 'process-order' }, { event: 'order/created' },
async ({ event, step }) => {
const payment = await step.run('charge-payment', () => chargeCustomer(event.data.paymentMethod))
await step.run('send-confirmation', () => sendOrderConfirmation(event.data.orderId))
return { status: 'completed', paymentId: payment.id }
}
)
完整的 Inngest 函数和 Trigger.dev 定时任务替代方案:references/data-and-jobs.md §Background jobs、§Alternatives。
速率限制 [HIGH freedom]
- 使用
@upstash/ratelimit,通过Redis.fromEnv()配置Ratelimit.slidingWindow(10, '10 s')。 - 使用用户 ID(匿名用户则使用 IP)作为键;在
!success时,返回Too many requests,并根据reset返回以秒为单位的retryAfter。
完整的 rateLimitedAction:references/request-patterns.md §Rate limiting。
架构模式(分布式系统) [HIGH freedom]
Gateway、BFF、bulkhead、circuit breaker、outbox+CDC、saga、hexagonal、ACL 和 strangler-fig →
references/architecture-patterns.md。根据拓扑选择模式(单体架构无需服务网格;只有读写出现分化时才采用 CQRS)。超时/重试/幂等性
→ audit-resilience;结构性缺口报告 → audit-backend-architecture。
验证 [LOW freedom — 不要跳过]
实现后端模式后:
- 错误处理 → 捕获并记录所有错误,返回安全的响应
- 身份验证检查 → 每次变更操作都验证身份
- 输入验证 → 对所有输入使用 Zod schema
- 速率限制 → 保护敏感端点
- 幂等性 → 关键操作能够处理重试
- 日志记录 → 记录结构化日志,不包含敏感数据
- 测试 → 为业务逻辑编写单元测试,为 API 编写集成测试