architect
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseArchitect — System Design
架构设计 — 系统架构
Structure the system before building it. Good architecture makes everything easier. Bad architecture makes everything a rewrite.
在构建系统前先进行架构设计。优秀的架构会让所有事情变得简单,糟糕的架构则会导致所有内容都需要重写。
Step 0: Understand Constraints
步骤0:明确约束条件
Before designing, answer:
- Scale — 100 users or 100,000? Determines everything.
- Team size — Solo founder or 10 engineers? Simpler systems for smaller teams.
- Budget — Bootstrapped or funded? Managed services vs self-hosted.
- Timeline — MVP in 2 weeks or v1 in 3 months?
- Compliance — HIPAA, SOC 2, GDPR? Constrains architecture choices.
在开始设计前,先回答以下问题:
- 规模 — 是100个用户还是100,000个用户?这决定了所有设计选择。
- 团队规模 — 是独立创始人还是10人工程师团队?小团队适合更简单的系统。
- 预算 — 是自筹资金还是有外部投资?选择托管服务还是自部署?
- 时间线 — 是2周内完成MVP还是3个月内推出v1版本?
- 合规要求 — 是否需要符合HIPAA、SOC 2、GDPR等标准?这会限制架构选项。
Architecture Patterns
架构模式
| Pattern | When to Use | When to Avoid |
|---|---|---|
| Monolith | <10 engineers, single product, moving fast | Multiple teams needing independent deploys |
| Modular monolith | Growing team, want boundaries without infra cost | Need independent scaling per service |
| Microservices | 20+ engineers, distinct domains, independent scaling | Small team, early stage, unclear boundaries |
| Serverless | Event-driven, spiky traffic, want zero ops | Long-running processes, cost-sensitive at scale |
| Event-driven | Async workflows, decoupled systems, audit trails | Simple CRUD, real-time requirements |
Default: Monolith until it hurts. Premature microservices is the #1 architecture mistake.
| 模式 | 适用场景 | 避免场景 |
|---|---|---|
| 单体架构 | 团队人数少于10人、单一产品、快速迭代 | 多团队需要独立部署的场景 |
| 模块化单体架构 | 团队规模增长,希望在不增加基础设施成本的前提下划分边界 | 需要按服务独立扩容的场景 |
| 微服务架构 | 团队人数20+、业务领域清晰、需要独立扩容 | 小团队、早期阶段、业务边界不明确的场景 |
| 无服务器架构 | 事件驱动、流量波动大、希望零运维 | 长运行时进程、规模化后对成本敏感的场景 |
| 事件驱动架构 | 异步工作流、解耦系统、审计追踪 | 简单CRUD操作、实时性要求高的场景 |
默认选择:在单体架构遇到明显瓶颈前,不要轻易切换。过早采用微服务是排名第一的架构设计错误。
Database Selection
数据库选型
| Need | Database | Why |
|---|---|---|
| General purpose, relational | PostgreSQL | ACID, JSON support, extensions, ecosystem |
| Key-value, caching | Redis / Valkey | Sub-ms reads, TTL, pub/sub |
| Document store, flexible schema | MongoDB | Rapid prototyping, nested documents |
| Full-text search | PostgreSQL FTS or Meilisearch | Postgres built-in is good enough until it isn't |
| Time-series | TimescaleDB (Postgres extension) | Keep one database engine |
| Graph relationships | PostgreSQL with recursive CTEs | Don't add Neo4j unless graph is the core product |
| Vector / embeddings | pgvector (Postgres extension) | Same — keep one database |
Rules:
- Start with Postgres. Add specialized databases only when Postgres can't do the job.
- Managed always (Supabase, Neon, RDS). Don't manage your own database.
- One database engine until you have a DBA. Two databases = two problems.
| 需求 | 数据库 | 原因 |
|---|---|---|
| 通用型、关系型 | PostgreSQL | 支持ACID、JSON、扩展插件,生态完善 |
| 键值对、缓存 | Redis / Valkey | 亚毫秒级读取、支持TTL、发布/订阅 |
| 文档型、灵活Schema | MongoDB | 快速原型开发、支持嵌套文档 |
| 全文搜索 | PostgreSQL FTS 或 Meilisearch | 在性能不足前,Postgres内置的全文搜索足够使用 |
| 时序数据 | TimescaleDB(Postgres扩展) | 保持单一数据库引擎 |
| 图关系 | PostgreSQL(配合递归CTE) | 除非图是核心产品,否则不要引入Neo4j |
| 向量/嵌入 | pgvector(Postgres扩展) | 同上 — 保持单一数据库引擎 |
规则:
- 从PostgreSQL开始。只有当PostgreSQL无法满足需求时,再引入专用数据库。
- 始终使用托管服务(如Supabase、Neon、RDS),不要自行管理数据库。
- 在拥有专职DBA前,只使用一种数据库引擎。两种数据库意味着两倍的问题。
Project Structure
项目结构
TypeScript / Next.js
TypeScript / Next.js
src/
├── app/ # Next.js app router — pages and layouts
│ ├── (auth)/ # Route groups for auth pages
│ ├── (dashboard)/ # Route groups for app pages
│ └── api/ # API routes
├── lib/ # Shared utilities, config, constants
│ ├── db/ # Database client, schema, migrations
│ ├── auth/ # Auth config and helpers
│ └── utils/ # Pure utility functions
├── services/ # Business logic — one file per domain
│ ├── user.service.ts
│ └── billing.service.ts
├── components/ # React components
│ ├── ui/ # Primitives (button, input, card)
│ └── features/ # Feature-specific composites
└── types/ # Shared TypeScript typessrc/
├── app/ # Next.js 应用路由 — 页面与布局
│ ├── (auth)/ # 路由分组:认证相关页面
│ ├── (dashboard)/ # 路由分组:应用主页面
│ └── api/ # API 路由
├── lib/ # 共享工具、配置、常量
│ ├── db/ # 数据库客户端、Schema、迁移脚本
│ ├── auth/ # 认证配置与辅助工具
│ └── utils/ # 纯工具函数
├── services/ # 业务逻辑 — 每个领域一个文件
│ ├── user.service.ts
│ └── billing.service.ts
├── components/ # React 组件
│ ├── ui/ # 基础组件(按钮、输入框、卡片)
│ └── features/ # 特定功能的复合组件
└── types/ # 共享 TypeScript 类型Python / FastAPI
Python / FastAPI
src/
├── api/ # Route handlers
│ ├── v1/ # Versioned endpoints
│ └── deps.py # Shared dependencies (auth, db session)
├── core/ # Config, security, constants
├── models/ # SQLAlchemy models
├── schemas/ # Pydantic request/response schemas
├── services/ # Business logic — one file per domain
├── repositories/ # Data access layer
└── tests/
├── unit/
└── integration/Rules:
- Feature code stays together. Don't scatter a feature across 8 directories.
- Services contain business logic. Routes are thin — validate, call service, respond.
- One service per domain. not
user.service.ts,getUserById.ts, etc.updateUser.ts
src/
├── api/ # 路由处理器
│ ├── v1/ # 版本化接口
│ └── deps.py # 共享依赖(认证、数据库会话)
├── core/ # 核心配置、安全、常量
├── models/ # SQLAlchemy 模型
├── schemas/ # Pydantic 请求/响应 Schema
├── services/ # 业务逻辑 — 每个领域一个文件
├── repositories/ # 数据访问层
└── tests/
├── unit/
└── integration/规则:
- 功能代码要集中存放,不要将一个功能分散到8个目录中。
- 服务层包含业务逻辑,路由层要简洁——仅做验证、调用服务、返回响应。
- 每个领域对应一个服务文件,比如使用,而不是拆分成
user.service.ts、getUserById.ts等多个文件。updateUser.ts
API Design
API设计
| Decision | Default |
|---|---|
| Protocol | REST for CRUD, tRPC for type-safe full-stack, GraphQL only if multiple clients need different shapes |
| Versioning | URL path: |
| Auth | Bearer token in Authorization header |
| Pagination | Cursor-based for feeds, offset for admin tables |
| Errors | |
| Rate limiting | 100 req/min default, lower for auth endpoints |
| 决策项 | 默认选择 |
|---|---|
| 协议 | CRUD场景用REST,全栈类型安全场景用tRPC,仅当多个客户端需要不同数据结构时才用GraphQL |
| 版本控制 | URL路径: |
| 认证 | 在Authorization头中使用Bearer令牌 |
| 分页 | 信息流用基于游标分页,后台表格用基于偏移量分页 |
| 错误处理 | 格式为 |
| 限流 | 默认100次请求/分钟,认证接口限流阈值更低 |
Caching Strategy
缓存策略
| Layer | Tool | TTL | Use When |
|---|---|---|---|
| Browser | Cache-Control headers | Varies | Static assets, API responses |
| CDN | Cloudflare / Vercel Edge | 1-60 min | Public pages, images |
| Application | Redis / in-memory | 5-60 min | Expensive queries, session data |
| Database | Materialized views | Refresh on write | Aggregations, dashboards |
Rules:
- Cache reads, not writes. Invalidate on mutation.
- Start with no cache. Add caching when you measure a bottleneck.
- Every cache needs an invalidation strategy. "TTL and hope" works until it doesn't.
| 层级 | 工具 | 过期时间(TTL) | 适用场景 |
|---|---|---|---|
| 浏览器 | Cache-Control 响应头 | 按需设置 | 静态资源、API响应 |
| 内容分发网络(CDN) | Cloudflare / Vercel Edge | 1-60分钟 | 公开页面、图片 |
| 应用层 | Redis / 内存缓存 | 5-60分钟 | 高开销查询、会话数据 |
| 数据库层 | 物化视图 | 写入时刷新 | 聚合查询、仪表盘 |
规则:
- 缓存读操作,不要缓存写操作。数据变更时要失效缓存。
- 初始阶段不使用缓存。只有当检测到性能瓶颈时再添加缓存。
- 每个缓存都需要失效策略。“依赖TTL过期”的方式在初期有效,但无法解决所有问题。
Scaling Checklist
规模化 Checklist
Only optimize when you hit the problem:
| Users | Likely Bottleneck | Fix |
|---|---|---|
| 0-1K | Nothing | Don't optimize |
| 1K-10K | Database queries | Add indexes, optimize N+1s |
| 10K-100K | Database connections | Connection pooling (PgBouncer) |
| 100K-1M | Read throughput | Add Redis cache layer |
| 1M+ | Write throughput | Read replicas, sharding, queue writes |
The best architecture is the simplest one that handles your current scale + 10×.
只有当遇到问题时再进行优化:
| 用户规模 | 可能的瓶颈 | 解决方案 |
|---|---|---|
| 0-1K | 无 | 无需优化 |
| 1K-10K | 数据库查询 | 添加索引、优化N+1查询 |
| 10K-100K | 数据库连接数 | 连接池(PgBouncer) |
| 100K-1M | 读吞吐量 | 添加Redis缓存层 |
| 1M+ | 写吞吐量 | 读副本、分片、写入队列 |
最佳架构是能够处理当前规模10倍增长的最简单架构。