scalable-thinking · diff
git:20260325.da398da to git:20260410.d55a9ea
21 added, 149 removed. Audit A to A.
---
name: scalable-thinking
description: "Design for scale while keeping implementation simple (KISS)."
autoInvoke: false
priority: high
triggers:
- "architecture"
- "API design"
- "data modeling"
- "database schema"
---
# Skill: Scalable Thinking
- **Purpose:** Design for scale while keeping implementation simple (KISS)
- **Priority:** HIGH
- **Auto-invokes:** Architecture, API design, data modeling, database schema
-
- ---
-
- ## Core Philosophy
-
- **"Think Scalable, Build Simple"**
+ **Principle:** Think Scalable, Build Simple.
| Aspect | Scalable Thinking (WHAT) | KISS (HOW) |
|--------|--------------------------|------------|
| Data Model | Normalized, indexed | Simple queries |
| API | Versioned, RESTful | Standard CRUD |
| Code Structure | Feature-based | Flat hierarchy |
| Config | Centralized | Single file |
---
## Where to Apply
- ### 1. Data Models
-
- **❌ Non-Scalable:**
- ```typescript
- interface User {
- id: string
- preferences: string // JSON string - can't query
- }
- ```
-
- **✅ Scalable (Simple Implementation):**
- ```typescript
- interface User { id: string; name: string; email: string }
- interface UserPreference { userId: string; key: string; value: string }
-
- // Simple queries, can index by key, can partition by userId
- ```
-
- ### 2. API Design
-
- **❌ Non-Scalable:**
- ```
- POST /api/process { everything... }
- ```
-
- **✅ Scalable (Simple):**
- ```
- POST /api/v1/users/:userId/processes
- GET /api/v1/processes/:processId
- ```
-
- Benefits: Versionable, RESTful, cacheable, evolvable
-
- ### 3. Database Schema
-
- **❌ Non-Scalable:**
- ```sql
- CREATE TABLE orders (
- id UUID PRIMARY KEY,
- items JSON -- Can't filter by item
- );
- ```
-
- **✅ Scalable (Simple):**
- ```sql
- CREATE TABLE orders (
- id UUID PRIMARY KEY,
- user_id UUID REFERENCES users(id),
- INDEX idx_user_id (user_id)
- );
-
- CREATE TABLE order_items (
- order_id UUID REFERENCES orders(id),
- product_id UUID,
- INDEX idx_order_id (order_id)
- );
- ```
+ ### Data Models
+ Separate related data into proper tables (not JSON strings). Enables querying, indexing, partitioning.
- ### 4. File Structure
+ ### APIs
+ RESTful resource paths with versioning: `/api/v1/users/:userId/processes`. Cacheable, evolvable.
- **❌ Non-Scalable:**
- ```
- src/utils.ts # 5000 lines
- src/components.tsx # All components
- ```
+ ### Database
+ Normalized tables with foreign keys and indexes. Not JSON blobs that can't be filtered.
- **✅ Scalable:**
- ```
- src/features/auth/hooks/, components/, api/
- src/features/posts/hooks/, components/, api/
- src/shared/hooks/, components/, utils/
- ```
+ ### File Structure
+ Feature-based: `src/features/{feature}/{hooks,components,api}/` + `src/shared/`.
---
## Scalable Patterns
- ### Always Plan For Pagination
-
- ```typescript
- // ❌ Returns all records
- GET /api/users → [...50,000 users]
-
- // ✅ Cursor-based
- GET /api/users?limit=20&cursor=abc123
- → { data: [...], pagination: { nextCursor, hasMore } }
- ```
-
- ### Centralized Configuration
-
- ```typescript
- const config = {
- api: { baseUrl: process.env.API_URL, timeout: 5000 },
- features: { /* feature flags */ },
- limits: { maxFileSize: 10 * 1024 * 1024 }
- }
- ```
-
- ### Structured Error Handling
-
- ```typescript
- class AppError extends Error {
- constructor(
- message: string,
- public code: string,
- public statusCode: number = 500
- ) { super(message) }
- }
-
- throw new AppError('User not found', 'USER_NOT_FOUND', 404)
- ```
+ - **Pagination:** Cursor-based `?limit=20&cursor=abc` with `{ nextCursor, hasMore }`
+ - **Centralized config:** Single config object with env-based values
+ - **Structured errors:** `AppError` with code + statusCode
---
- ## Anti-Patterns to Avoid
+ ## Anti-Patterns
- | Anti-Pattern | Instead Do |
- |--------------|------------|
- | Build for hypothetical 1M users | Simple monolith first, scale when data shows need |
- | Pre-optimize with Redis | In-memory cache first, add Redis when measured |
- | Abstract for 1 use case | Direct implementation, abstract at 2-3 examples |
+ | Anti-Pattern | Instead |
+ |--------------|---------|
+ | Build for hypothetical 1M users | Simple monolith first |
+ | Pre-optimize with Redis | In-memory cache, add Redis when measured |
+ | Abstract for 1 use case | Direct impl, abstract at 2-3 examples |
| Microservices from day 1 | Monolith, split when team/features grow |
---
## Checklist
- ### Before Designing
- - [ ] Can data model support 10x more records?
- - [ ] Can I query the data I'll need?
- - [ ] Are there natural partition keys (userId, orgId)?
- - [ ] Is API versioned (/v1)?
- - [ ] Does pagination exist for lists?
+ **Before designing:** Can model support 10x? Can I query needed data? Natural partition keys? API versioned? Pagination for lists?
- ### During Implementation
- - [ ] Am I using standard patterns?
- - [ ] Is this the simplest solution?
- - [ ] Can a junior dev understand this?
- - [ ] No abstractions until 3+ examples?
+ **During:** Standard patterns? Simplest solution? Junior dev understandable? No abstractions until 3+ examples?
---
## When to Scale Up
- **Add Complexity When:**
- - Database queries > 2s consistently
- - API response > 500ms at p95
- - Error rate > 1%
- - User growth > 10x in 3 months
- - Team size > 5 developers
-
- **Until Then:** Keep it simple, measure everything
-
- ---
-
- ## Summary
-
- 1. **Think Scalable:** Data models that grow, APIs that evolve, architecture that supports change
- 2. **Build Simple:** Simplest implementation first, standard patterns, no premature optimization
- 3. **Iterate:** Add complexity based on data, refactor when patterns emerge
-
- **Remember:** Scalable ≠ Complex. Scalable = Can grow. KISS = Simple to maintain.
+ Add complexity when: DB queries > 2s, API p95 > 500ms, error rate > 1%, 10x growth in 3 months, team > 5. Until then: keep simple, measure everything.
---
-
- **Applied In:** Phase 2 (Design), Phase 5 (Implementation)