Token导航 LogoToken导航

Agent Skill · 研究检索

architecture-decision-records(架构决策记录)

architecture-decision-records 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

architecture-decision-records 是研究检索类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证信息还不明确,第三方扫描已通过,按安装量在研究检索类的 73,675 个 Skill 里排第 67,721。

总安装 242周安装 10GitHub Stars 公开资料未说明下载 79核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:architecture-decision-records(架构决策记录)
来源仓库:https://github.com/tejovanthn/rasikalife
仓库路径:skills/architecture-decision-records
安装命令:
npx skills add https://github.com/tejovanthn/rasikalife --skill architecture-decision-records
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/tejovanthn/rasikalife --skill architecture-decision-records

这个 Skill 是做什么的

研究检索类 Skill 主要解决「找资料、核对事实、把来源整理清楚」的问题,通常会让助手先检索再总结。

architecture-decision-records 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词快速定位候选结果时使用。适用于架构决策记录查找、历史方案回顾和技术债务分析等研究检索场景。

通过关键词或任务场景输入,返回匹配的候选信息列表供进一步处理。安装命令:npx skills add https://github.com/tejovanthn/rasikalife --skill architecture-decision-records。使用前请确认仓库维护状态及是否涉及文件读写或网络请求权限。

来源仓库内路径:skills/architecture-decision-records

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/tejovanthn/rasikalife --skill architecture-dec…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

architecture-decision-records 怎么安装?

在终端执行 npx skills add https://github.com/tejovanthn/rasikalife --skill architecture-decision-reco…。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

architecture-decision-records 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

architecture-decision-records 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

architecture-decision-records 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

architecture-decision-records 用的人多吗?

公开数据是累计安装 242 次,近一周安装 10 次,下载 79 次。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

architecture-decision-records 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理研究检索类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

研究检索类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
find-skills

寻找技能 · Codex、Claude

31,199,81316,486操作浏览器MIT有提醒
self-improving-agent

自我改进 Agent · OpenClaw

16,464,0023,396接触敏感数据MIT-0通过
soultrace

灵魂追踪 · Codex、Claude

7,588,94412需要联网未明确有提醒
self-improving

自我完善 · OpenClaw

6,829,2841,046需要联网MIT-0通过
microsoft-foundry

微软代工厂 · Codex、Claude

6,614,144764调用外部服务未明确有提醒
architecture-decision-records

架构决策记录 · 本页

242—需要联网未明确通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Architecture Decision Records (ADR) - Writing Guide

This skill provides comprehensive guidance for writing high-quality Architecture Decision Records (ADRs) for the VedaGhosham project, based on the existing 13 ADRs in docs/architecture-decisions/.

What is an ADR?

An Architecture Decision Record documents a significant technical decision made during the project's development. ADRs capture:

  • What decision was made
  • Why it was made (problem context)
  • How it's implemented (with code examples)
  • Trade-offs (what was gained/lost)
  • Alternatives considered

When to Write an ADR

Write an ADR when making decisions that:

  1. Impact the entire system (database choice, framework selection, deployment strategy)
  2. Are difficult to reverse (DynamoDB single-table design, monorepo structure)
  3. Involve significant trade-offs (tRPC vs REST, Remix vs Next.js)
  4. Set architectural patterns (entity structure, error handling, authentication)
  5. Require future context (why we chose this approach over alternatives)

Examples of ADR-Worthy Decisions

  • ✅ Choosing DynamoDB single-table design (ADR-004)
  • ✅ Selecting tRPC over REST (ADR-005)
  • ✅ Email blacklist management strategy (ADR-015)
  • ✅ Fresh user data from database vs JWT (ADR-001)
  • ✅ Monorepo with pnpm workspaces (ADR-009)

Examples of Non-ADR Decisions

  • ❌ Adding a new field to an entity (routine change)
  • ❌ Refactoring a component (implementation detail)
  • ❌ Fixing a bug (not an architectural decision)
  • ❌ Updating dependencies (maintenance task)

ADR Format and Structure

File Naming Convention

docs/architecture-decisions/adr-NNN-kebab-case-title.md
  • NNN: Zero-padded 3-digit number (001, 002, 015, etc.)
  • kebab-case-title: Descriptive, lowercase, hyphen-separated
  • Find the next number by checking existing ADRs

Examples:

  • adr-001-fresh-user-data.md
  • adr-005-trpc-over-rest.md
  • adr-015-email-blacklist-bounce-management.md

Document Structure

Every ADR follows this structure:

# ADR-NNN: Title (Clear, Concise Description)

**Date:** YYYY-MM-DD
**Status:** Accepted | Proposed | Deprecated | Superseded
**Context:** One-line summary of when/why this decision was needed

---

## Problem

[Detailed problem description with 3-5 paragraphs]

### Option 1: [First Alternative]
[Code example or description]

**Problems:**
- List specific issues
- Technical limitations
- Business concerns

### Option 2: [Second Alternative]
[Code example or description]

**Problems:**
- List specific issues

### Option 3: [Chosen Approach]
[Code example or description]

**Benefits:**
- Why this is better
- Advantages over alternatives

---

## Decision

**Use [Chosen Approach] for [Purpose].**

[1-2 paragraph explanation of the decision]

**Why [Chosen Approach]:**
1. Reason 1
2. Reason 2
3. Reason 3

---

## Implementation

[Detailed implementation with code examples]

### 1. [First Implementation Aspect]
[Code examples with comments]

### 2. [Second Implementation Aspect]
[Code examples with comments]

[Continue for all major implementation aspects]

---

## Benefits

### 1. **[Benefit Name]**
[Explanation with code/metrics examples]

### 2. **[Benefit Name]**
[Explanation with code/metrics examples]

[Continue for all major benefits]

---

## Trade-offs

### What We Gained
- ✅ Benefit 1
- ✅ Benefit 2
- ✅ Benefit 3

### What We Lost
- ❌ Limitation 1
- ❌ Limitation 2
- ❌ Limitation 3

### Why Trade-offs Are Acceptable
1. **Limitation 1**: Explanation of why it's acceptable
2. **Limitation 2**: Explanation
3. **Limitation 3**: Explanation

---

## Comparison

| Feature | Alternative 1 | Alternative 2 | Chosen Approach |
|---------|--------------|---------------|-----------------|
| **Metric 1** | Value | Value | Value |
| **Metric 2** | Value | Value | Value |

---

## Real-World Example

### Scenario: [Concrete Use Case]

**With [Alternative Approach]:**

[Step-by-step flow showing problems]

**With [Chosen Approach]:**

[Step-by-step flow showing benefits]

**Winner:** [Chosen Approach] ([quantified benefit])

---

## Future Considerations

### [Future Topic 1]
[Discussion of how this decision might evolve]

### [Future Topic 2]
[Potential extensions or modifications]

**Current Status:** [Current state and future plans]

---

## Related Files

### [Category 1]
- `path/to/file1.ts` - Description
- `path/to/file2.ts` - Description

### [Category 2]
- `path/to/file3.ts` - Description

---

## References

- **[Resource Name]**: [URL]
- **[Documentation]**: [URL]
- Related: [Cross-reference to other ADRs]

Writing Guidelines

1. Title and Header

Title Format:

# ADR-NNN: Clear, Concise Description

Examples:

  • ✅ ADR-001: Load Fresh User Data from Database (Not Stale JWT)
  • ✅ ADR-005: tRPC Over REST API
  • ✅ ADR-015: Email Blacklist and Bounce Management
  • ❌ ADR-001: User Data (too vague)
  • ❌ ADR-005: API Decision (not descriptive)

Header Fields:

**Date:** 2025-12-17 (ISO format)
**Status:** Accepted (current state)
**Context:** Brief one-liner about when/why this decision was needed

Status Values:

  • Proposed - Under consideration
  • Accepted - Active and implemented
  • Deprecated - No longer recommended
  • Superseded - Replaced by another ADR (reference ADR-XXX)

2. Problem Section

The Problem section should:

  • Explain the context (3-5 paragraphs minimum)
  • Show code examples of the problem or alternatives
  • List 2-4 alternatives considered
  • Explain trade-offs for each alternative

Good Problem Description Example:

## Problem

VedaGhosham sends authentication OTP emails via AWS SES. Without proper bounce
and complaint handling, we risk:

1. **Sender Reputation Damage**: Repeated bounces to invalid emails harm sender reputation
2. **Service Suspension**: AWS SES may suspend service if bounce rate exceeds 5%
3. **Wasted Resources**: Sending emails to blacklisted addresses wastes API calls and costs
4. **Poor User Experience**: Users with invalid emails get stuck in auth flow
5. **No Visibility**: No tracking of email delivery issues or spam complaints

### Without Blacklist Management

// ❌ Sends to all emails without checking export async function sendOTPEmail(email: string, code: string) { // Always sends, even if email previously bounced await sesClient.send(new SendEmailCommand({ ... })); }


**Problems:**

- Hard bounces (permanent failures) get retried every login
- Spam complaints not tracked (user marked email as spam)
- No way to prevent sending to known-bad addresses
- AWS SES reputation degrades over time

Key Points:

  • Start with business impact (reputation, cost, UX)
  • Show concrete code examples
  • List specific, actionable problems

3. Decision Section

Format:

## Decision

**Use [Technology/Pattern] for [Purpose].**

[1-2 paragraph justification]

**Why [Chosen Approach]:**
1. Reason 1 (with evidence)
2. Reason 2 (with evidence)
3. Reason 3 (with evidence)

Example:

## Decision

**Use tRPC (TypeScript Remote Procedure Call) instead of REST or GraphQL.**

tRPC provides end-to-end type safety without codegen, perfect for our TypeScript monorepo.

**Why tRPC:**
1. **Full type safety with zero codegen**: Types flow automatically through AppRouter export
2. **Automatic validation**: Zod schemas validate input before handler runs
3. **Middleware composition**: Reusable auth/permission middleware
4. **Request batching**: Reduces Lambda invocations and latency

4. Implementation Section

The Implementation section should:

  • Show working code examples (not pseudocode)
  • Include file paths in code comments
  • Explain key patterns with inline comments
  • Cover all major aspects of implementation

Structure:

## Implementation

### 1. [Infrastructure/Configuration]
[SST/config code with explanations]

### 2. [Core Business Logic]
[Entity/service code]

### 3. [API Layer]
[tRPC router/endpoint code]

### 4. [Frontend Integration]
[Remix route/component code]

### 5. [Testing/Monitoring]
[Test examples, CloudWatch alarms]

Code Example Standards:

// ✅ Good: Working code with comments
// packages/core/src/email/blacklist.ts
export async function checkEmailBlacklist(
  email: string,
): Promise<BlacklistCheckResult> {
  const normalizedEmail = normalizeEmail(email);

  try {
    const result = await User.query.byEmail({ email: normalizedEmail }).go();

    if (result.data.length > 0) {
      const user = result.data[0];

      if (user.emailBlacklisted) {
        return {
          isBlacklisted: true,
          reason: user.emailBlacklistReason || 'UNKNOWN',
          userId: user.userId,
          blacklistedAt: user.emailBlacklistedAt,
        };
      }
    }

    return { isBlacklisted: false };
  } catch (error) {
    // Database error - fail open to prevent auth system breakage
    console.error('Failed to check email blacklist, allowing send:', error);
    return { isBlacklisted: false };
  }
}

// ❌ Bad: Pseudocode without context
function checkBlacklist(email) {
  // Check if email is blacklisted
  return query(email);
}

5. Benefits Section

Format:

## Benefits

### 1. **[Concrete Benefit]**
[Explanation with evidence]

**Example/Metric:**
[Code example or quantified metric]

### 2. **[Concrete Benefit]**
[Explanation with evidence]

Good Benefits Example:

## Benefits

### 1. **Cost Efficiency**
Single table = one set of provisioned capacity. No cross-table query overhead.

**Example:**
- Multi-table: 7 tables × $5/month = **$35/month** (minimum)
- Single-table: 1 table × $5/month = **$5/month**
- **Savings: 85%** (at small scale)

### 2. **Consistent Performance**
All queries within one table (no cross-table latency). GSIs provide O(1) lookups
for all access patterns. Single-digit millisecond latency.

Key Points:

  • Use bold for benefit names
  • Provide concrete evidence (metrics, code examples)
  • Quantify when possible (percentages, time, cost)

6. Trade-offs Section

Format:

## Trade-offs

### What We Gained
- ✅ Benefit 1
- ✅ Benefit 2
- ✅ Benefit 3

### What We Lost
- ❌ Limitation 1
- ❌ Limitation 2
- ❌ Limitation 3

### Why Trade-offs Are Acceptable

1. **Limitation 1**: Detailed explanation of why this is acceptable
2. **Limitation 2**: Explanation with context
3. **Limitation 3**: Explanation

Good Trade-offs Example:

## Trade-offs

### What We Gained
- ✅ Full type safety with zero codegen
- ✅ Automatic validation (Zod schemas)
- ✅ Simplified error handling (TRPCError)
- ✅ Middleware composition for auth/permissions
- ✅ Request batching (reduces Lambda invocations)
- ✅ IntelliSense for all procedures

### What We Lost
- ❌ No OpenAPI/Swagger documentation (tRPC-specific)
- ❌ Smaller ecosystem than REST (fewer tools/integrations)
- ❌ TypeScript-only (can't call from Python, Go, etc.)
- ❌ Less familiar to REST-only developers

### Why Trade-offs Are Acceptable

1. **No OpenAPI**: Internal API only (not public-facing); tRPC docs are code itself
2. **Smaller Ecosystem**: TypeScript ecosystem is sufficient for our needs
3. **TypeScript-Only**: Entire stack is TypeScript (no other languages planned)
4. **Learning Curve**: One-time cost; tRPC is simpler than REST + OpenAPI codegen

7. Comparison Section

Use tables to compare alternatives across multiple dimensions:

## Comparison

| Feature | Alternative 1 | Alternative 2 | Chosen Approach |
|---------|--------------|---------------|-----------------|
| **Feature 1** | ❌ No | ⚠️ Partial | ✅ Yes |
| **Feature 2** | Value | Value | Value |
| **Cost** | $X/month | $Y/month | $Z/month |
| **Performance** | Metric | Metric | Metric |

Symbols to Use:

  • ✅ = Advantage
  • ❌ = Disadvantage
  • ⚠️ = Partial/Conditional
  • Use actual values when possible (numbers, percentages)

8. Real-World Example

Provide a concrete scenario showing the decision in action:

## Real-World Example

### Scenario: Add "dateOfBirth" field to User

**With Polyrepo (Multi-Repository):**

1. Update core

cd vedaghosham-core

Edit User entity

git commit -m "Add dateOfBirth" npm version patch # 1.2.0 → 1.2.1 npm publish

2. Update API

cd ../vedaghosham-api npm install @vedaghosham/core@1.2.1 # Wait for npm registry propagation

Update API code

git commit -m "Support dateOfBirth"

3. Update Web

cd ../vedaghosham-web npm install @vedaghosham/core@1.2.1

Update web code

git commit -m "Show dateOfBirth in profile"

Total time: 30-60 minutes


**With Monorepo (Chosen Approach):**

1. Update core

cd packages/core/src/user

Edit entity.ts and types.ts

2. Update functions (TypeScript error guides you!)

cd packages/functions/src/user

Update router.ts

3. Update web (TypeScript error guides you!)

cd packages/web/app/routes

Update profile route

4. Commit everything

git commit -m "Add dateOfBirth field"

Total time: 5-10 minutes ✅


**Winner:** Monorepo (6× faster, no versioning hassle)

9. Future Considerations

Discuss how the decision might evolve:

## Future Considerations

### Adding Public API
If we need a public API (for mobile apps, third-party integrations):
- **Option A**: Keep tRPC for internal use; add separate REST API for public
- **Option B**: Use tRPC + tRPC-OpenAPI adapter (generates OpenAPI from tRPC)

**Current Status:** Internal API only; no public API needed yet.

### Non-TypeScript Clients
If we need Python/Go clients:
- **Option A**: Create thin REST wrapper around tRPC backend
- **Option B**: Use HTTP directly (tRPC is just JSON-RPC over HTTP)

**Current Status:** Full TypeScript stack; no other languages planned.

10. Related Files

List all files implementing the decision:

## Related Files

### Backend
- `packages/functions/src/shared/trpc.ts` - tRPC initialization
- `packages/functions/src/shared/middleware.ts` - Auth middleware
- `packages/functions/src/{entity}/router.ts` - Entity routers

### Frontend
- `packages/web/app/lib/trpc.ts` - tRPC client factory
- `packages/web/app/routes/_app.*.tsx` - Usage in Remix routes

### Schemas
- `packages/core/src/{entity}/schema.ts` - Zod schemas used by tRPC

11. References

Include all relevant resources:

## References

- **tRPC Documentation**: https://trpc.io/
- **tRPC vs REST**: https://trpc.io/docs/concepts
- **ElectricSQL tRPC Talk**: https://www.youtube.com/watch?v=2LYM8gf184U
- **Zod Validation**: https://zod.dev/
- Related: ADR-004 (Single-Table DynamoDB)
- Related: ADR-010 (Zod Shared Validation)

Code Example Standards

1. Use Real, Working Code

// ✅ Good: Actual code from codebase
export async function loader({ request }: LoaderFunctionArgs) {
  await requireAuth(request);
  const trpc = await createServerClient(request);
  const user = await trpc.user.me.query();
  return json({ user });
}

// ❌ Bad: Pseudocode
export function loader() {
  // Get user
  return user;
}

2. Include File Paths

// ✅ Good: Shows where code lives
// packages/web/app/routes/_app.tsx
export async function loader({ request }: LoaderFunctionArgs) {
  // ...
}

// ❌ Bad: No context
export async function loader() {
  // ...
}

3. Add Explanatory Comments

// ✅ Good: Explains why
try {
  const result = await User.query.byEmail({ email: normalizedEmail }).go();
  return { isBlacklisted: false };
} catch (error) {
  // Database error - fail open to prevent auth system breakage
  console.error('Failed to check email blacklist, allowing send:', error);
  return { isBlacklisted: false };
}

// ❌ Bad: No explanation for non-obvious behavior
} catch (error) {
  return { isBlacklisted: false };
}

4. Show Before/After

// ❌ WRONG: Checks stale JWT token
export async function loader({ request }: LoaderFunctionArgs) {
  const userData = await requireCompleteProfile(request);
  // userData.profileCompleted is STALE!
}

// ✅ CORRECT: Loads fresh data from database
export async function loader({ request }: LoaderFunctionArgs) {
  await requireAuth(request);
  const trpc = await createServerClient(request);
  const user = await trpc.user.me.query();
  // user.profileCompleted is always fresh! ✅
}

Writing Style Guidelines

1. Be Concrete, Not Abstract

  • ✅ "Single table costs $5/month vs multi-table $35/month (85% savings)"
  • ❌ "Single table is cheaper"

2. Use Numbers and Metrics

  • ✅ "3-6× faster initial load (300-500ms vs 2-3 seconds)"
  • ❌ "Much faster initial load"

3. Show, Don't Just Tell

  • ✅ Include code examples showing the problem and solution
  • ❌ "The old approach had issues"

4. Explain Trade-offs Honestly

  • ✅ "What we lost: No OpenAPI docs. Why acceptable: Internal API only"
  • ❌ "Perfect solution with no downsides"

5. Future-Proof with Considerations

  • ✅ "If we need public API: Option A vs Option B. Current status: Not needed"
  • ❌ "We'll never need a public API"

Common Pitfalls to Avoid

❌ Don't Write Vague ADRs

## Decision
We decided to use a database.

❌ Don't Skip Alternatives

## Problem
We need to store data.

## Decision
Use DynamoDB.

(Missing: Why not PostgreSQL? MongoDB? What were the trade-offs?)

❌ Don't Use Pseudocode

function doSomething() {
  // Do the thing
}

❌ Don't Ignore Trade-offs

## Benefits
- Fast
- Cheap
- Easy

(Missing: What did we lose? Every decision has trade-offs)

❌ Don't Skip Real Examples

## Implementation
We implemented the feature.

(Missing: How? Show code!)

Checklist for Reviewing ADRs

Before finalizing an ADR, ensure:

  • Title is clear and descriptive (ADR-NNN format)
  • Date is in YYYY-MM-DD format
  • Status is set (Proposed/Accepted/Deprecated/Superseded)
  • Problem section explains context with 3+ paragraphs
  • Alternatives section lists 2-4 options considered
  • Decision section has clear justification (3+ reasons)
  • Implementation has real code examples with file paths
  • Benefits section quantifies advantages (metrics/percentages)
  • Trade-offs section honestly discusses limitations
  • Comparison table compares alternatives across multiple dimensions
  • Real-World Example shows concrete scenario
  • Future Considerations discusses evolution/extensions
  • Related Files lists all implementation files
  • References includes external docs and cross-references
  • Code examples use ✅/❌ to show right/wrong patterns
  • Numbers and metrics used throughout (not just "better/faster")
  • All code examples include comments explaining why

ADR Template

Use this template when creating a new ADR:

# ADR-NNN: [Title]

**Date:** YYYY-MM-DD
**Status:** Proposed | Accepted | Deprecated | Superseded
**Context:** [One-line summary]

---

## Problem

[3-5 paragraph problem description]

### Option 1: [First Alternative]
[Code/description]

**Problems:**
- Issue 1
- Issue 2

### Option 2: [Second Alternative]
[Code/description]

**Problems:**
- Issue 1
- Issue 2

---

## Decision

**Use [Chosen Approach] for [Purpose].**

[1-2 paragraph justification]

**Why [Chosen Approach]:**
1. Reason 1
2. Reason 2
3. Reason 3

---

## Implementation

### 1. [Implementation Aspect 1]
[Code examples]

### 2. [Implementation Aspect 2]
[Code examples]

---

## Benefits

### 1. **[Benefit Name]**
[Explanation with evidence]

### 2. **[Benefit Name]**
[Explanation with evidence]

---

## Trade-offs

### What We Gained
- ✅ Benefit 1
- ✅ Benefit 2

### What We Lost
- ❌ Limitation 1
- ❌ Limitation 2

### Why Trade-offs Are Acceptable
1. **Limitation 1**: Explanation
2. **Limitation 2**: Explanation

---

## Comparison

| Feature | Alternative 1 | Alternative 2 | Chosen |
|---------|--------------|---------------|--------|
| **Feature 1** | Value | Value | Value |

---

## Real-World Example

### Scenario: [Use Case]

**With [Alternative]:**
[Step-by-step flow]

**With [Chosen Approach]:**
[Step-by-step flow]

**Winner:** [Chosen] ([quantified benefit])

---

## Future Considerations

### [Topic 1]
[Discussion]

**Current Status:** [State]

---

## Related Files

### [Category 1]
- `path/to/file.ts` - Description

---

## References

- **[Resource]**: [URL]
- Related: ADR-XXX

Example: Simplified ADR

Here's a simplified example showing the key elements:

# ADR-016: Rate Limiting for API Endpoints

**Date:** 2025-12-20
**Status:** Proposed
**Context:** Protecting API from abuse and ensuring fair usage

---

## Problem

VedaGhosham's tRPC API is publicly accessible (after authentication). Without
rate limiting, we risk:

1. **DoS Attacks**: Malicious users could overwhelm Lambda functions
2. **Cost Spikes**: Unlimited requests = unlimited AWS costs
3. **Poor UX**: One user's heavy usage slows down others
4. **No Abuse Protection**: No mechanism to block bad actors

### Option 1: No Rate Limiting

// No protection - anyone can spam requests export const userRouter = router({ list: protectedProcedure.query(async () => { return await User.scan.go(); // Expensive query, no limits }), });


**Problems:**

- No protection against abuse
- AWS costs unbounded
- Poor experience for legitimate users

### Option 2: Lambda Concurrency Limits

Set reserved concurrency on Lambda functions.

**Problems:**

- All-or-nothing (affects all users equally)
- No per-user fairness
- Hard to configure correctly

### Option 3: DynamoDB-Based Rate Limiting

Track request counts per user in DynamoDB with TTL.

**Benefits:**

- Per-user fairness
- Serverless (no Redis needed)
- Fine-grained control

---

## Decision

**Use DynamoDB-based rate limiting with per-user counters and TTL.**

We'll create a RateLimit entity tracking requests per user per time window.

**Why DynamoDB Rate Limiting:**

1. **Serverless**: No Redis/Memcached infrastructure needed
2. **Per-User Fairness**: Each user has independent limit
3. **Automatic Cleanup**: DynamoDB TTL removes old records
4. **Fine-Grained**: Can set limits per endpoint or globally

---

## Implementation

### 1. RateLimit Entity

// packages/core/src/rate-limit/entity.ts export const RateLimit = new Entity({ model: { entity: 'RateLimit', version: '1', service: 'vedaghosham', }, attributes: { userId: { type: 'string', required: true }, endpoint: { type: 'string', required: true }, windowStart: { type: 'number', required: true }, // Unix timestamp requestCount: { type: 'number', required: true, default: 0 }, ttl: { type: 'number' }, // DynamoDB TTL (auto-delete after 1 hour) }, indexes: { primary: { pk: { field: 'pk', composite: ['userId', 'endpoint'] }, sk: { field: 'sk', composite: ['windowStart'] }, }, }, }, configuration);


### 2. Rate Limiting Middleware

// packages/functions/src/shared/rate-limit.ts const RATE_LIMITS = { 'user.list': { requests: 100, windowMs: 60000 }, // 100 req/min 'course.create': { requests: 10, windowMs: 60000 }, // 10 req/min default: { requests: 1000, windowMs: 60000 }, // 1000 req/min };

export const rateLimitMiddleware = t.middleware(async ({ ctx, path, next }) => { const userId = ctx.user?.userId; if (!userId) return next(); // Skip for unauthenticated

const limit = RATE_LIMITS[path] || RATE_LIMITS.default; const windowStart = Math.floor(Date.now() / limit.windowMs) * limit.windowMs;

// Check current count const result = await RateLimit.get({ userId, endpoint: path, windowStart, }).go();

if (result.data && result.data.requestCount >= limit.requests) { throw new TRPCError({ code: 'TOO_MANY_REQUESTS', message: Rate limit exceeded. Try again in ${limit.windowMs / 1000}s, }); }

// Increment counter await RateLimit.upsert({ userId, endpoint: path, windowStart, requestCount: (result.data?.requestCount || 0) + 1, ttl: Math.floor(Date.now() / 1000) + 3600, // Expire after 1 hour }).go();

return next(); });


### 3. Apply to Procedures

// packages/functions/src/shared/procedures.ts export const protectedProcedure = t.procedure .use(isAuthenticated) .use(rateLimitMiddleware);


---

## Benefits

### 1. **Cost Protection**

Rate limiting prevents runaway costs from abuse.

**Example:**

- Without limit: Malicious user makes 1M requests = $200+ Lambda cost
- With limit: Blocked at 1,000 requests = $0.20 maximum cost per user
- **Savings: 99.9%** in abuse scenario

### 2. **Fair Resource Allocation**

Each user has independent quota (one user can't starve others).

### 3. **No Additional Infrastructure**

Uses existing DynamoDB table (no Redis/Memcached needed).

---

## Trade-offs

### What We Gained

- ✅ Protection from abuse and DoS
- ✅ Cost predictability
- ✅ Per-user fairness
- ✅ Serverless (no Redis)

### What We Lost

- ❌ DynamoDB write costs (1 write per request)
- ❌ Slight latency increase (~10ms per request)
- ❌ Complexity (middleware + entity)

### Why Trade-offs Are Acceptable

1. **DynamoDB Writes**: ~$0.001 per 1,000 requests (negligible vs abuse cost)
2. **Latency**: 10ms overhead acceptable for cost/abuse protection
3. **Complexity**: Essential for production API

---

## Comparison

| Feature | No Limit | Lambda Limits | DynamoDB Limit |
| --- | --- | --- | --- |
| **Cost Protection** | ❌ No | ⚠️ Global | ✅ Per-user |
| **Fairness** | ❌ No | ❌ No | ✅ Yes |
| **Infrastructure** | ✅ None | ✅ None | ✅ Existing DB |
| **Granularity** | N/A | ❌ Coarse | ✅ Fine-grained |

---

## Real-World Example

### Scenario: User spams "list all courses" endpoint

**Without Rate Limiting:**

User makes 10,000 requests in 1 minute → 10,000 Lambda invocations × $0.0000002 = $2.00 → 10,000 DynamoDB scans × $0.00025 = $2.50 → Total cost: $4.50 per abuse incident → API slow for all users


**With Rate Limiting (100 req/min):**

User makes 10,000 requests in 1 minute → First 100 succeed → Next 9,900 blocked with 429 error → Cost: 100 requests = $0.045 → Other users unaffected


**Winner:** Rate limiting (99% cost reduction, better UX)

---

## Future Considerations

### Distributed Rate Limiting

If we need multi-region:

- Use DynamoDB Global Tables for consistent limits across regions

**Current Status:** Single region sufficient.

### Redis Alternative

If DynamoDB becomes too expensive:

- Switch to ElastiCache Redis (faster, lower per-request cost)

**Current Status:** DynamoDB cost acceptable (<$1/month).

---

## Related Files

### Core

- `packages/core/src/rate-limit/entity.ts` - RateLimit entity

### Functions

- `packages/functions/src/shared/rate-limit.ts` - Middleware
- `packages/functions/src/shared/procedures.ts` - Applied to procedures

### Infrastructure

- `infra/database.ts` - DynamoDB table (already has TTL enabled)

---

## References

- **DynamoDB TTL**: [https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TTL.html](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TTL.html)
- **Rate Limiting Patterns**: [https://aws.amazon.com/blogs/architecture/rate-limiting-strategies-for-serverless-applications/](https://aws.amazon.com/blogs/architecture/rate-limiting-strategies-for-serverless-applications/)
- **tRPC Middleware**: [https://trpc.io/docs/server/middlewares](https://trpc.io/docs/server/middlewares)
- Related: ADR-004 (Single-Table DynamoDB)
- Related: ADR-005 (tRPC Over REST)

Summary

High-quality ADRs in VedaGhosham:

  1. Document significant decisions (not routine changes)
  2. Show alternatives considered (2-4 options with trade-offs)
  3. Provide working code examples (real code from codebase)
  4. Quantify benefits (metrics, percentages, cost savings)
  5. Explain trade-offs honestly (what we lost and why it's acceptable)
  6. Include comparison tables (features across alternatives)
  7. Show real-world scenarios (concrete before/after examples)
  8. Discuss future evolution (how decision might change)
  9. List all related files (where implementation lives)
  10. Reference external docs (AWS docs, library docs, related ADRs)

Use the ADR template and checklist to ensure comprehensive, maintainable architecture documentation that will serve the project for years to come.

平台分布

Codex

34.16%
按下载量换算27

Claude

32.95%
按下载量换算26

Cursor

17.48%
按下载量换算14

Gemini CLI

8.83%
按下载量换算7

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills