forgecommandline 0.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- forgecli/__init__.py +2 -0
- forgecli/ads.py +322 -0
- forgecli/agent.py +1093 -0
- forgecli/art.py +574 -0
- forgecli/attach.py +246 -0
- forgecli/brief.py +215 -0
- forgecli/browsercheck.py +99 -0
- forgecli/checkpoints.py +81 -0
- forgecli/city.py +833 -0
- forgecli/cli.py +1668 -0
- forgecli/config.py +194 -0
- forgecli/courier.py +177 -0
- forgecli/courier_data.py +164 -0
- forgecli/courier_hd.py +431 -0
- forgecli/courier_hd_data.bin +0 -0
- forgecli/courier_hd_data.py +19 -0
- forgecli/ghlogin.py +76 -0
- forgecli/github.py +54 -0
- forgecli/guards.py +403 -0
- forgecli/hooks.py +50 -0
- forgecli/httpapi.py +434 -0
- forgecli/images.py +110 -0
- forgecli/keys.py +152 -0
- forgecli/keyvault.py +320 -0
- forgecli/mcp.py +674 -0
- forgecli/memory.py +42 -0
- forgecli/openapi.py +331 -0
- forgecli/parallel.py +308 -0
- forgecli/prices.py +72 -0
- forgecli/procs.py +144 -0
- forgecli/providers.py +758 -0
- forgecli/quality.py +192 -0
- forgecli/repomap.py +78 -0
- forgecli/roster.py +227 -0
- forgecli/safety.py +93 -0
- forgecli/sandbox.py +83 -0
- forgecli/sessions.py +97 -0
- forgecli/skills.py +446 -0
- forgecli/tools.py +1184 -0
- forgecli/ui.py +860 -0
- forgecli/worktrees.py +79 -0
- forgecommandline-0.8.0.data/data/skills/commit/SKILL.md +14 -0
- forgecommandline-0.8.0.data/data/skills/debug/SKILL.md +17 -0
- forgecommandline-0.8.0.data/data/skills/explain/SKILL.md +14 -0
- forgecommandline-0.8.0.data/data/skills/init/SKILL.md +19 -0
- forgecommandline-0.8.0.data/data/skills/library/LICENSES/agent-skills-MIT.txt +21 -0
- forgecommandline-0.8.0.data/data/skills/library/LICENSES/wondelai-MIT.txt +23 -0
- forgecommandline-0.8.0.data/data/skills/library/README.md +9 -0
- forgecommandline-0.8.0.data/data/skills/library/_references/accessibility-checklist.md +160 -0
- forgecommandline-0.8.0.data/data/skills/library/_references/definition-of-done.md +67 -0
- forgecommandline-0.8.0.data/data/skills/library/_references/observability-checklist.md +92 -0
- forgecommandline-0.8.0.data/data/skills/library/_references/orchestration-patterns.md +370 -0
- forgecommandline-0.8.0.data/data/skills/library/_references/performance-checklist.md +238 -0
- forgecommandline-0.8.0.data/data/skills/library/_references/security-checklist.md +248 -0
- forgecommandline-0.8.0.data/data/skills/library/_references/testing-patterns.md +235 -0
- forgecommandline-0.8.0.data/data/skills/library/api-and-interface-design/SKILL.md +367 -0
- forgecommandline-0.8.0.data/data/skills/library/architecture-optimization/SKILL.md +279 -0
- forgecommandline-0.8.0.data/data/skills/library/architecture-optimization/references/artifact-templates.md +157 -0
- forgecommandline-0.8.0.data/data/skills/library/architecture-optimization/references/methods.md +87 -0
- forgecommandline-0.8.0.data/data/skills/library/awwwards-tier-web-application/SKILL.md +877 -0
- forgecommandline-0.8.0.data/data/skills/library/browser-testing-with-devtools/SKILL.md +317 -0
- forgecommandline-0.8.0.data/data/skills/library/ci-cd-and-automation/SKILL.md +390 -0
- forgecommandline-0.8.0.data/data/skills/library/code-review-and-quality/SKILL.md +398 -0
- forgecommandline-0.8.0.data/data/skills/library/code-simplification/SKILL.md +331 -0
- forgecommandline-0.8.0.data/data/skills/library/constraint-driven-development/SKILL.md +311 -0
- forgecommandline-0.8.0.data/data/skills/library/constraint-driven-development/references/floor-guard.md +182 -0
- forgecommandline-0.8.0.data/data/skills/library/context-engineering/SKILL.md +353 -0
- forgecommandline-0.8.0.data/data/skills/library/debugging-and-error-recovery/SKILL.md +300 -0
- forgecommandline-0.8.0.data/data/skills/library/deprecation-and-migration/SKILL.md +247 -0
- forgecommandline-0.8.0.data/data/skills/library/documentation-and-adrs/SKILL.md +297 -0
- forgecommandline-0.8.0.data/data/skills/library/doubt-driven-development/SKILL.md +243 -0
- forgecommandline-0.8.0.data/data/skills/library/frontend-ui-engineering/SKILL.md +340 -0
- forgecommandline-0.8.0.data/data/skills/library/git-workflow-and-versioning/SKILL.md +355 -0
- forgecommandline-0.8.0.data/data/skills/library/idea-refine/SKILL.md +193 -0
- forgecommandline-0.8.0.data/data/skills/library/idea-refine/examples.md +238 -0
- forgecommandline-0.8.0.data/data/skills/library/idea-refine/frameworks.md +99 -0
- forgecommandline-0.8.0.data/data/skills/library/idea-refine/refinement-criteria.md +113 -0
- forgecommandline-0.8.0.data/data/skills/library/idea-refine/scripts/idea-refine.sh +15 -0
- forgecommandline-0.8.0.data/data/skills/library/improve-code-quality/SKILL.md +275 -0
- forgecommandline-0.8.0.data/data/skills/library/improve-code-quality/references/artifact-templates.md +101 -0
- forgecommandline-0.8.0.data/data/skills/library/incremental-implementation/SKILL.md +249 -0
- forgecommandline-0.8.0.data/data/skills/library/interview-me/SKILL.md +235 -0
- forgecommandline-0.8.0.data/data/skills/library/observability-and-instrumentation/SKILL.md +238 -0
- forgecommandline-0.8.0.data/data/skills/library/performance-optimization/SKILL.md +267 -0
- forgecommandline-0.8.0.data/data/skills/library/performance-optimization/references/optimization-patterns.md +250 -0
- forgecommandline-0.8.0.data/data/skills/library/planning-and-task-breakdown/SKILL.md +257 -0
- forgecommandline-0.8.0.data/data/skills/library/remove-technical-debt/SKILL.md +203 -0
- forgecommandline-0.8.0.data/data/skills/library/remove-technical-debt/references/artifact-templates.md +79 -0
- forgecommandline-0.8.0.data/data/skills/library/security-and-hardening/SKILL.md +216 -0
- forgecommandline-0.8.0.data/data/skills/library/security-and-hardening/references/hardening-patterns.md +324 -0
- forgecommandline-0.8.0.data/data/skills/library/shipping-and-launch/SKILL.md +336 -0
- forgecommandline-0.8.0.data/data/skills/library/source-driven-development/SKILL.md +216 -0
- forgecommandline-0.8.0.data/data/skills/library/spec-driven-development/SKILL.md +259 -0
- forgecommandline-0.8.0.data/data/skills/library/system-design/SKILL.md +207 -0
- forgecommandline-0.8.0.data/data/skills/library/system-design/references/building-blocks.md +272 -0
- forgecommandline-0.8.0.data/data/skills/library/system-design/references/common-designs.md +257 -0
- forgecommandline-0.8.0.data/data/skills/library/system-design/references/database-scaling.md +295 -0
- forgecommandline-0.8.0.data/data/skills/library/system-design/references/estimation-numbers.md +250 -0
- forgecommandline-0.8.0.data/data/skills/library/system-design/references/four-step-process.md +286 -0
- forgecommandline-0.8.0.data/data/skills/library/system-design/references/reliability-operations.md +373 -0
- forgecommandline-0.8.0.data/data/skills/library/test-driven-development/SKILL.md +398 -0
- forgecommandline-0.8.0.data/data/skills/library/using-agent-skills/SKILL.md +192 -0
- forgecommandline-0.8.0.data/data/skills/review/SKILL.md +16 -0
- forgecommandline-0.8.0.data/data/skills/run/SKILL.md +17 -0
- forgecommandline-0.8.0.data/data/skills/security-review/SKILL.md +20 -0
- forgecommandline-0.8.0.data/data/skills/simplify/SKILL.md +18 -0
- forgecommandline-0.8.0.data/data/skills/test/SKILL.md +16 -0
- forgecommandline-0.8.0.data/data/skills/web-build/SKILL.md +25 -0
- forgecommandline-0.8.0.dist-info/METADATA +357 -0
- forgecommandline-0.8.0.dist-info/RECORD +113 -0
- forgecommandline-0.8.0.dist-info/WHEEL +5 -0
- forgecommandline-0.8.0.dist-info/entry_points.txt +2 -0
- forgecommandline-0.8.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
# Database Design and Scaling
|
|
2
|
+
|
|
3
|
+
How to choose, design, and scale databases for distributed systems. The database is usually the first bottleneck -- understanding scaling strategies lets you plan growth deliberately.
|
|
4
|
+
|
|
5
|
+
## SQL vs NoSQL Decision Framework
|
|
6
|
+
|
|
7
|
+
### When to Choose SQL (Relational)
|
|
8
|
+
|
|
9
|
+
Choose relational databases (PostgreSQL, MySQL, Oracle) when:
|
|
10
|
+
|
|
11
|
+
- **ACID transactions** are required (financial data, inventory, bookings)
|
|
12
|
+
- **Complex joins** across multiple tables are common
|
|
13
|
+
- **Schema is well-defined** and unlikely to change dramatically
|
|
14
|
+
- **Data integrity** via foreign keys and constraints is critical
|
|
15
|
+
- **Reporting and ad-hoc queries** are needed (SQL is incredibly expressive)
|
|
16
|
+
|
|
17
|
+
### When to Choose NoSQL
|
|
18
|
+
|
|
19
|
+
Choose NoSQL when the access pattern matches a specific NoSQL model:
|
|
20
|
+
|
|
21
|
+
| NoSQL Type | Best For | Examples | When to Use |
|
|
22
|
+
|-----------|----------|---------|-------------|
|
|
23
|
+
| **Key-Value** | Simple lookups by key | Redis, DynamoDB, Riak | Session storage, caching, user preferences |
|
|
24
|
+
| **Document** | Flexible schema, nested data | MongoDB, CouchDB, Firestore | Product catalogs, content management, user profiles |
|
|
25
|
+
| **Wide-Column** | High write throughput, time-series | Cassandra, HBase, ScyllaDB | IoT data, event logs, messaging history |
|
|
26
|
+
| **Graph** | Highly connected data | Neo4j, Amazon Neptune, JanusGraph | Social networks, recommendation engines, fraud detection |
|
|
27
|
+
|
|
28
|
+
### The Decision Checklist
|
|
29
|
+
|
|
30
|
+
| Question | If Yes: SQL | If Yes: NoSQL |
|
|
31
|
+
|----------|-------------|---------------|
|
|
32
|
+
| Need ACID transactions? | SQL | |
|
|
33
|
+
| Need complex joins? | SQL | |
|
|
34
|
+
| Schema is stable? | SQL | |
|
|
35
|
+
| Schema evolves rapidly? | | Document DB |
|
|
36
|
+
| Need horizontal write scaling? | | Wide-column or Key-value |
|
|
37
|
+
| Access pattern is simple key lookup? | | Key-value |
|
|
38
|
+
| Data is highly connected (graph)? | | Graph DB |
|
|
39
|
+
| Need full-text search? | | Consider Elasticsearch alongside primary DB |
|
|
40
|
+
|
|
41
|
+
**Important:** Many real systems use multiple databases (polyglot persistence). A social app might use PostgreSQL for user accounts, Redis for sessions, Cassandra for the activity feed, and Elasticsearch for search.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Vertical Scaling (Scale Up)
|
|
46
|
+
|
|
47
|
+
### What It Means
|
|
48
|
+
|
|
49
|
+
Make a single server more powerful: more CPU, more RAM, faster disks, more network bandwidth.
|
|
50
|
+
|
|
51
|
+
### Advantages
|
|
52
|
+
|
|
53
|
+
- Simple -- no code changes required
|
|
54
|
+
- No distributed systems complexity
|
|
55
|
+
- Strong consistency is easy (single node)
|
|
56
|
+
- No need for sharding logic
|
|
57
|
+
|
|
58
|
+
### Limitations
|
|
59
|
+
|
|
60
|
+
- Hard ceiling -- you can't buy an infinitely powerful machine
|
|
61
|
+
- Single point of failure -- one server, one failure domain
|
|
62
|
+
- Cost increases non-linearly -- a 2x more powerful server costs more than 2x the price
|
|
63
|
+
- Downtime during upgrade -- usually requires restart
|
|
64
|
+
|
|
65
|
+
### When to Use
|
|
66
|
+
|
|
67
|
+
- Early-stage products where simplicity matters more than scale
|
|
68
|
+
- When vertical limits haven't been reached (modern servers can handle significant load)
|
|
69
|
+
- When strong consistency requirements make horizontal scaling very difficult
|
|
70
|
+
|
|
71
|
+
**Rule of thumb:** Start vertical. A single PostgreSQL server with 64 cores and 256 GB RAM handles more than most applications need. Move to horizontal when you actually hit the limits.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Replication
|
|
76
|
+
|
|
77
|
+
### Leader-Follower (Master-Slave)
|
|
78
|
+
|
|
79
|
+
The most common replication pattern:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
Writes -> Leader (Primary)
|
|
83
|
+
Reads -> Leader or Followers (Replicas)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**How it works:**
|
|
87
|
+
1. All writes go to the leader
|
|
88
|
+
2. Leader writes to its write-ahead log (WAL)
|
|
89
|
+
3. Followers replicate the WAL and apply changes
|
|
90
|
+
4. Reads can go to any node (leader or follower)
|
|
91
|
+
|
|
92
|
+
**Advantages:**
|
|
93
|
+
- Scales reads horizontally (add more followers)
|
|
94
|
+
- Provides redundancy (promote a follower if leader fails)
|
|
95
|
+
- Simple mental model
|
|
96
|
+
|
|
97
|
+
**Challenges:**
|
|
98
|
+
|
|
99
|
+
| Challenge | Description | Mitigation |
|
|
100
|
+
|-----------|------------|------------|
|
|
101
|
+
| **Replication lag** | Followers may be seconds behind leader | Read-your-writes: route user's reads to leader after they write |
|
|
102
|
+
| **Failover complexity** | Promoting a follower requires coordination | Automated failover with consensus (e.g., Patroni for PostgreSQL) |
|
|
103
|
+
| **Write bottleneck** | All writes still go to one node | See sharding section below |
|
|
104
|
+
|
|
105
|
+
### Multi-Leader (Master-Master)
|
|
106
|
+
|
|
107
|
+
Multiple nodes accept writes:
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
Region A writes -> Leader A -> replicates to -> Leader B
|
|
111
|
+
Region B writes -> Leader B -> replicates to -> Leader A
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**When to use:**
|
|
115
|
+
- Multi-region deployments where each region needs local writes
|
|
116
|
+
- Offline-capable applications (each device is a "leader")
|
|
117
|
+
|
|
118
|
+
**The hard problem: write conflicts.** When two leaders modify the same row:
|
|
119
|
+
|
|
120
|
+
| Strategy | How It Works | Tradeoff |
|
|
121
|
+
|----------|-------------|----------|
|
|
122
|
+
| **Last-write-wins (LWW)** | Timestamp-based, latest wins | Simple but can lose data |
|
|
123
|
+
| **Application-level merge** | App defines custom merge logic | Correct but complex |
|
|
124
|
+
| **CRDTs** | Conflict-free data structures | Automatic merge but limited data types |
|
|
125
|
+
| **Conflict avoidance** | Route same data to same leader | Simple but limits flexibility |
|
|
126
|
+
|
|
127
|
+
### Leaderless Replication
|
|
128
|
+
|
|
129
|
+
All nodes are equal; reads and writes go to multiple nodes:
|
|
130
|
+
|
|
131
|
+
- Write to W nodes, read from R nodes
|
|
132
|
+
- If W + R > N (total nodes), reads are guaranteed to see latest write
|
|
133
|
+
- Used by Cassandra and DynamoDB
|
|
134
|
+
|
|
135
|
+
**Advantages:** No single point of failure, high availability
|
|
136
|
+
**Disadvantages:** Complex consistency model, conflict resolution needed
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Sharding (Horizontal Partitioning)
|
|
141
|
+
|
|
142
|
+
### What It Means
|
|
143
|
+
|
|
144
|
+
Split data across multiple database servers (shards), each holding a subset of the data. Each shard is a fully independent database.
|
|
145
|
+
|
|
146
|
+
### When to Shard
|
|
147
|
+
|
|
148
|
+
Shard only when you have exhausted simpler options:
|
|
149
|
+
1. Vertical scaling (bigger server)
|
|
150
|
+
2. Read replicas (for read-heavy workloads)
|
|
151
|
+
3. Caching (for hot data)
|
|
152
|
+
4. Query optimization (indexes, query rewriting)
|
|
153
|
+
5. **Then** shard (for write-heavy workloads or data too large for one server)
|
|
154
|
+
|
|
155
|
+
### Sharding Strategies
|
|
156
|
+
|
|
157
|
+
#### Hash-Based Sharding
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
shard_number = hash(shard_key) % number_of_shards
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
| Pros | Cons |
|
|
164
|
+
|------|------|
|
|
165
|
+
| Even data distribution | Adding/removing shards requires data redistribution |
|
|
166
|
+
| Simple implementation | Range queries across shards are difficult |
|
|
167
|
+
| No hotspots (if hash is good) | Re-sharding is expensive |
|
|
168
|
+
|
|
169
|
+
**Mitigation for redistribution:** Use consistent hashing instead of simple modulo.
|
|
170
|
+
|
|
171
|
+
#### Range-Based Sharding
|
|
172
|
+
|
|
173
|
+
```
|
|
174
|
+
Shard 1: user_id 1 - 1,000,000
|
|
175
|
+
Shard 2: user_id 1,000,001 - 2,000,000
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
| Pros | Cons |
|
|
179
|
+
|------|------|
|
|
180
|
+
| Efficient range queries | Uneven distribution (hotspots) |
|
|
181
|
+
| Natural data locality | New data may overwhelm one shard |
|
|
182
|
+
| Simple to understand | Requires manual range management |
|
|
183
|
+
|
|
184
|
+
**Best for:** Time-series data (shard by month), geographic data (shard by region).
|
|
185
|
+
|
|
186
|
+
#### Directory-Based Sharding
|
|
187
|
+
|
|
188
|
+
A lookup service maps each key to its shard:
|
|
189
|
+
|
|
190
|
+
```
|
|
191
|
+
Lookup table:
|
|
192
|
+
user_123 -> shard_3
|
|
193
|
+
user_456 -> shard_1
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
| Pros | Cons |
|
|
197
|
+
|------|------|
|
|
198
|
+
| Flexible, any key-to-shard mapping | Lookup service is a single point of failure |
|
|
199
|
+
| Easy rebalancing | Extra network hop for every query |
|
|
200
|
+
| Can handle hotspots by moving individual keys | Directory itself needs to be highly available |
|
|
201
|
+
|
|
202
|
+
### Choosing a Shard Key
|
|
203
|
+
|
|
204
|
+
The shard key determines everything about your sharding strategy. Choose carefully:
|
|
205
|
+
|
|
206
|
+
| Criteria | Why It Matters |
|
|
207
|
+
|----------|---------------|
|
|
208
|
+
| **High cardinality** | More distinct values = more even distribution |
|
|
209
|
+
| **Even distribution** | Avoid hotspots where one shard gets disproportionate traffic |
|
|
210
|
+
| **Query patterns** | Most queries should hit a single shard (avoid scatter-gather) |
|
|
211
|
+
| **Growth stability** | Key shouldn't cause imbalance as data grows |
|
|
212
|
+
|
|
213
|
+
**Common shard keys:**
|
|
214
|
+
- `user_id` -- good for user-centric applications (each user's data on one shard)
|
|
215
|
+
- `tenant_id` -- good for multi-tenant SaaS (each tenant isolated)
|
|
216
|
+
- `geo_region` -- good for location-based services
|
|
217
|
+
- `created_at` -- good for time-series (but recent shard gets all writes)
|
|
218
|
+
|
|
219
|
+
### The Celebrity/Hotspot Problem
|
|
220
|
+
|
|
221
|
+
Even with good hash-based sharding, a single popular entity can overwhelm one shard.
|
|
222
|
+
|
|
223
|
+
**Example:** A celebrity with 100 million followers. Any action on their account generates massive read/write traffic on the shard that holds their data.
|
|
224
|
+
|
|
225
|
+
**Solutions:**
|
|
226
|
+
1. **Dedicated shard:** Move the hot entity to its own shard
|
|
227
|
+
2. **Secondary partition:** Split the hot entity's data further (e.g., partition followers into sub-groups)
|
|
228
|
+
3. **Caching:** Put a cache in front of the hot shard
|
|
229
|
+
4. **Application-level routing:** Detect hot keys and handle them differently
|
|
230
|
+
|
|
231
|
+
### Cross-Shard Operations
|
|
232
|
+
|
|
233
|
+
The biggest challenge with sharding: operations that span multiple shards.
|
|
234
|
+
|
|
235
|
+
| Operation | Challenge | Solution |
|
|
236
|
+
|-----------|----------|----------|
|
|
237
|
+
| **Joins** | Can't join across shards efficiently | Denormalize, or join at application level |
|
|
238
|
+
| **Aggregations** | Must scatter query to all shards and gather results | Pre-compute aggregates, use a separate analytics DB |
|
|
239
|
+
| **Transactions** | Distributed transactions are slow and complex | Design for single-shard transactions, use sagas for cross-shard |
|
|
240
|
+
| **Unique constraints** | Can't enforce uniqueness across shards | Use a global sequence service, or accept probabilistic uniqueness |
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Denormalization
|
|
245
|
+
|
|
246
|
+
### What It Means
|
|
247
|
+
|
|
248
|
+
Duplicate data across tables or documents to avoid expensive joins at read time.
|
|
249
|
+
|
|
250
|
+
### When to Denormalize
|
|
251
|
+
|
|
252
|
+
| Indicator | Example |
|
|
253
|
+
|-----------|---------|
|
|
254
|
+
| Read-heavy workload (100:1 read:write ratio) | News feed, product catalog |
|
|
255
|
+
| Joins are too slow | Dashboard aggregating data from 5+ tables |
|
|
256
|
+
| Data changes infrequently | User profile data embedded in every post |
|
|
257
|
+
| Scale requires sharding (joins across shards are impractical) | Any sharded system |
|
|
258
|
+
|
|
259
|
+
### Denormalization Patterns
|
|
260
|
+
|
|
261
|
+
| Pattern | How It Works | Example |
|
|
262
|
+
|---------|-------------|---------|
|
|
263
|
+
| **Embed related data** | Store related data in same row/document | Store author name in each post (not just author_id) |
|
|
264
|
+
| **Materialized view** | Pre-compute and store query results | Nightly job that joins orders + products into a summary table |
|
|
265
|
+
| **Counter cache** | Store computed counts alongside parent | `posts_count` column on user table, incremented on new post |
|
|
266
|
+
| **Summary table** | Aggregate data into a summary | Daily revenue summary table updated by background job |
|
|
267
|
+
|
|
268
|
+
### Tradeoffs
|
|
269
|
+
|
|
270
|
+
| Benefit | Cost |
|
|
271
|
+
|---------|------|
|
|
272
|
+
| Faster reads (no joins) | Slower writes (update multiple places) |
|
|
273
|
+
| Simpler queries | Data inconsistency risk |
|
|
274
|
+
| Works with sharding | More storage used |
|
|
275
|
+
| Reduced database load | Application must maintain consistency |
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## Database Selection Guide
|
|
280
|
+
|
|
281
|
+
Quick reference for choosing the right database:
|
|
282
|
+
|
|
283
|
+
| Requirement | Recommended | Examples |
|
|
284
|
+
|-------------|------------|---------|
|
|
285
|
+
| General-purpose web app | Relational | PostgreSQL, MySQL |
|
|
286
|
+
| Simple key-value lookups at massive scale | Key-value | Redis, DynamoDB |
|
|
287
|
+
| Flexible schema, document-oriented | Document | MongoDB, Firestore |
|
|
288
|
+
| High write throughput, time-series | Wide-column | Cassandra, ScyllaDB |
|
|
289
|
+
| Graph relationships | Graph | Neo4j, Neptune |
|
|
290
|
+
| Full-text search | Search engine | Elasticsearch, OpenSearch |
|
|
291
|
+
| Analytics and OLAP | Columnar | ClickHouse, BigQuery, Redshift |
|
|
292
|
+
| Caching layer | In-memory | Redis, Memcached |
|
|
293
|
+
| Message/event storage | Distributed log | Apache Kafka |
|
|
294
|
+
|
|
295
|
+
**Remember:** Most systems use 2-3 databases for different access patterns. This is polyglot persistence and it is normal at scale.
|
forgecommandline-0.8.0.data/data/skills/library/system-design/references/estimation-numbers.md
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# Back-of-the-Envelope Estimation
|
|
2
|
+
|
|
3
|
+
Essential numbers, formulas, and worked examples for estimating system capacity. The goal is order of magnitude, not precision -- being within 10x is success; being within 2x is excellent.
|
|
4
|
+
|
|
5
|
+
## Powers of Two
|
|
6
|
+
|
|
7
|
+
Every engineer should know these instantly:
|
|
8
|
+
|
|
9
|
+
| Power | Exact Value | Approximate |
|
|
10
|
+
|-------|-------------|-------------|
|
|
11
|
+
| 2^10 | 1,024 | 1 thousand (1 KB) |
|
|
12
|
+
| 2^20 | 1,048,576 | 1 million (1 MB) |
|
|
13
|
+
| 2^30 | 1,073,741,824 | 1 billion (1 GB) |
|
|
14
|
+
| 2^40 | 1,099,511,627,776 | 1 trillion (1 TB) |
|
|
15
|
+
| 2^50 | ~1.13 x 10^15 | 1 quadrillion (1 PB) |
|
|
16
|
+
|
|
17
|
+
**Quick conversions:**
|
|
18
|
+
- 1 KB = 10^3 bytes
|
|
19
|
+
- 1 MB = 10^6 bytes
|
|
20
|
+
- 1 GB = 10^9 bytes
|
|
21
|
+
- 1 TB = 10^12 bytes
|
|
22
|
+
- 1 PB = 10^15 bytes
|
|
23
|
+
|
|
24
|
+
**Useful round numbers:**
|
|
25
|
+
- 1 million seconds = ~11.5 days
|
|
26
|
+
- 1 billion seconds = ~31.7 years
|
|
27
|
+
- 86,400 seconds in a day (~10^5)
|
|
28
|
+
- 2.5 million seconds in a month (~2.5 x 10^6)
|
|
29
|
+
- 31.5 million seconds in a year (~3 x 10^7)
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Latency Numbers Every Programmer Should Know
|
|
34
|
+
|
|
35
|
+
These numbers, originally compiled by Jeff Dean, define the performance landscape:
|
|
36
|
+
|
|
37
|
+
| Operation | Latency | Notes |
|
|
38
|
+
|-----------|---------|-------|
|
|
39
|
+
| L1 cache reference | 0.5 ns | |
|
|
40
|
+
| Branch mispredict | 5 ns | |
|
|
41
|
+
| L2 cache reference | 7 ns | |
|
|
42
|
+
| Mutex lock/unlock | 25 ns | |
|
|
43
|
+
| Main memory reference | 100 ns | |
|
|
44
|
+
| Compress 1 KB with Snappy | 3 us | |
|
|
45
|
+
| Send 1 KB over 1 Gbps network | 10 us | |
|
|
46
|
+
| Read 4 KB randomly from SSD | 150 us | |
|
|
47
|
+
| Read 1 MB sequentially from memory | 250 us | |
|
|
48
|
+
| Round trip within same datacenter | 500 us | |
|
|
49
|
+
| Read 1 MB sequentially from SSD | 1 ms | |
|
|
50
|
+
| HDD disk seek | 10 ms | |
|
|
51
|
+
| Read 1 MB sequentially from HDD | 20 ms | |
|
|
52
|
+
| Send packet CA -> Netherlands -> CA | 150 ms | |
|
|
53
|
+
|
|
54
|
+
### Key Takeaways
|
|
55
|
+
|
|
56
|
+
1. **Memory is fast, disk is slow.** Memory access (~100 ns) is 100,000x faster than disk seek (~10 ms).
|
|
57
|
+
2. **SSD is much faster than HDD.** SSD random read (~150 us) is ~67x faster than HDD seek (~10 ms).
|
|
58
|
+
3. **Sequential reads are fast everywhere.** Sequential 1 MB from memory (250 us) vs SSD (1 ms) vs HDD (20 ms).
|
|
59
|
+
4. **Network within a datacenter is fast.** Round trip ~0.5 ms. Cross-continent is ~150 ms (300x slower).
|
|
60
|
+
5. **Compression is cheap.** Compressing 1 KB takes ~3 us -- almost always worth doing for network transfer.
|
|
61
|
+
|
|
62
|
+
### Design Implications
|
|
63
|
+
|
|
64
|
+
| Latency Requirement | Design Strategy |
|
|
65
|
+
|--------------------|-----------------|
|
|
66
|
+
| < 1 ms | Must be in memory (cache, in-process) |
|
|
67
|
+
| < 10 ms | Can hit SSD or local cache |
|
|
68
|
+
| < 100 ms | Can hit database (with indexes) or remote cache |
|
|
69
|
+
| < 500 ms | Can make 1-2 network calls within datacenter |
|
|
70
|
+
| < 1 second | Can make multiple datacenter calls or one cross-region call |
|
|
71
|
+
| > 1 second | Must be async, show loading state to user |
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Availability Nines
|
|
76
|
+
|
|
77
|
+
| Availability | Downtime/Year | Downtime/Month | Downtime/Week |
|
|
78
|
+
|-------------|---------------|----------------|---------------|
|
|
79
|
+
| 99% (two nines) | 3.65 days | 7.31 hours | 1.68 hours |
|
|
80
|
+
| 99.9% (three nines) | 8.77 hours | 43.83 minutes | 10.08 minutes |
|
|
81
|
+
| 99.95% | 4.38 hours | 21.92 minutes | 5.04 minutes |
|
|
82
|
+
| 99.99% (four nines) | 52.60 minutes | 4.38 minutes | 1.01 minutes |
|
|
83
|
+
| 99.999% (five nines) | 5.26 minutes | 26.30 seconds | 6.05 seconds |
|
|
84
|
+
|
|
85
|
+
### SLA Composition
|
|
86
|
+
|
|
87
|
+
When services depend on each other, availabilities multiply:
|
|
88
|
+
|
|
89
|
+
- Service A: 99.9%, Service B: 99.9%
|
|
90
|
+
- Combined (A depends on B): 99.9% x 99.9% = 99.8%
|
|
91
|
+
|
|
92
|
+
This means:
|
|
93
|
+
- A chain of 3 services at 99.9% each = 99.7% combined
|
|
94
|
+
- A chain of 5 services at 99.9% each = 99.5% combined
|
|
95
|
+
|
|
96
|
+
**Implication:** To achieve 99.99% end-to-end, each component must be significantly better than 99.99% individually, or you need redundancy (parallel paths) to improve overall availability.
|
|
97
|
+
|
|
98
|
+
**Parallel redundancy:**
|
|
99
|
+
- Two instances of a service, each at 99%: 1 - (0.01 x 0.01) = 99.99%
|
|
100
|
+
- Both must fail simultaneously for the system to be unavailable
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## QPS Estimation
|
|
105
|
+
|
|
106
|
+
### Formula
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
Average QPS = DAU x average_actions_per_user / 86,400
|
|
110
|
+
Peak QPS = Average QPS x peak_factor (typically 2-5x)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Worked Examples
|
|
114
|
+
|
|
115
|
+
**Twitter-like service:**
|
|
116
|
+
- DAU: 300 million
|
|
117
|
+
- Tweets per user per day: 2 (average)
|
|
118
|
+
- Tweet reads per user per day: 100
|
|
119
|
+
- Write QPS: 300M x 2 / 86,400 = ~7,000 QPS
|
|
120
|
+
- Peak write QPS: 7,000 x 3 = ~21,000 QPS
|
|
121
|
+
- Read QPS: 300M x 100 / 86,400 = ~350,000 QPS
|
|
122
|
+
- Peak read QPS: 350,000 x 3 = ~1,050,000 QPS
|
|
123
|
+
- Read:write ratio = 50:1
|
|
124
|
+
|
|
125
|
+
**URL shortener:**
|
|
126
|
+
- DAU: 100 million
|
|
127
|
+
- URLs created per user per day: 0.1 (most users only read)
|
|
128
|
+
- URL redirects per user per day: 5
|
|
129
|
+
- Write QPS: 100M x 0.1 / 86,400 = ~116 QPS
|
|
130
|
+
- Read QPS: 100M x 5 / 86,400 = ~5,800 QPS
|
|
131
|
+
- Peak read QPS: 5,800 x 5 = ~29,000 QPS
|
|
132
|
+
|
|
133
|
+
**Chat application:**
|
|
134
|
+
- DAU: 50 million
|
|
135
|
+
- Messages per user per day: 40
|
|
136
|
+
- Message QPS: 50M x 40 / 86,400 = ~23,000 QPS
|
|
137
|
+
- Peak QPS: 23,000 x 5 = ~115,000 QPS
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Storage Estimation
|
|
142
|
+
|
|
143
|
+
### Formula
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
Daily storage = records_per_day x average_record_size
|
|
147
|
+
Yearly storage = daily_storage x 365
|
|
148
|
+
Total storage = yearly_storage x retention_years
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Worked Examples
|
|
152
|
+
|
|
153
|
+
**Twitter-like service (5-year retention):**
|
|
154
|
+
- Tweets per day: 300M users x 2 tweets = 600M tweets
|
|
155
|
+
- Average tweet size: tweet_id (8 bytes) + user_id (8 bytes) + text (280 chars = 280 bytes) + timestamp (8 bytes) + metadata (100 bytes) = ~400 bytes
|
|
156
|
+
- Daily storage: 600M x 400 bytes = 240 GB/day
|
|
157
|
+
- Yearly storage: 240 GB x 365 = ~88 TB/year
|
|
158
|
+
- 5-year storage: 88 TB x 5 = ~440 TB
|
|
159
|
+
- With media (images, videos): multiply by 10-50x
|
|
160
|
+
|
|
161
|
+
**URL shortener (10-year retention):**
|
|
162
|
+
- New URLs per day: 100M x 0.1 = 10M URLs
|
|
163
|
+
- Average record size: short_code (7 bytes) + original_url (200 bytes) + metadata (50 bytes) = ~257 bytes, round to 300 bytes
|
|
164
|
+
- Daily storage: 10M x 300 bytes = 3 GB/day
|
|
165
|
+
- Yearly storage: 3 GB x 365 = ~1.1 TB/year
|
|
166
|
+
- 10-year storage: 1.1 TB x 10 = ~11 TB
|
|
167
|
+
|
|
168
|
+
**Chat application (indefinite retention):**
|
|
169
|
+
- Messages per day: 50M users x 40 messages = 2 billion messages
|
|
170
|
+
- Average message size: 200 bytes (text) + 100 bytes (metadata) = 300 bytes
|
|
171
|
+
- Daily storage: 2B x 300 bytes = 600 GB/day
|
|
172
|
+
- Yearly storage: 600 GB x 365 = ~219 TB/year
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Bandwidth Estimation
|
|
177
|
+
|
|
178
|
+
### Formula
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
Incoming bandwidth = write_QPS x average_request_size
|
|
182
|
+
Outgoing bandwidth = read_QPS x average_response_size
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Worked Examples
|
|
186
|
+
|
|
187
|
+
**URL shortener:**
|
|
188
|
+
- Write: 116 QPS x 300 bytes = ~35 KB/s (negligible)
|
|
189
|
+
- Read: 5,800 QPS x 500 bytes (redirect response) = ~2.9 MB/s
|
|
190
|
+
- Peak read: 29,000 QPS x 500 bytes = ~14.5 MB/s
|
|
191
|
+
|
|
192
|
+
**Image hosting service:**
|
|
193
|
+
- Upload: 100 QPS x 2 MB = 200 MB/s incoming
|
|
194
|
+
- Download: 10,000 QPS x 500 KB (average image) = 5 GB/s outgoing
|
|
195
|
+
- This immediately tells you: CDN is mandatory
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Server Count Estimation
|
|
200
|
+
|
|
201
|
+
### Rule of Thumb
|
|
202
|
+
|
|
203
|
+
- A single web server handles ~1,000-10,000 QPS (depends on workload complexity)
|
|
204
|
+
- A single database server handles ~5,000-10,000 QPS for simple queries
|
|
205
|
+
- A single cache server (Redis) handles ~100,000 QPS for simple GET/SET
|
|
206
|
+
- A single message queue node handles ~10,000-100,000 messages/second
|
|
207
|
+
|
|
208
|
+
### Formula
|
|
209
|
+
|
|
210
|
+
```
|
|
211
|
+
Server count = Peak QPS / QPS per server
|
|
212
|
+
Add redundancy factor (typically 2-3x for fault tolerance)
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Worked Example
|
|
216
|
+
|
|
217
|
+
**URL shortener:**
|
|
218
|
+
- Peak read QPS: 29,000
|
|
219
|
+
- QPS per web server: ~5,000 (lightweight redirect)
|
|
220
|
+
- Minimum web servers: 29,000 / 5,000 = ~6
|
|
221
|
+
- With redundancy: 6 x 2 = 12 web servers
|
|
222
|
+
- Cache QPS: 29,000 (cache all reads)
|
|
223
|
+
- Redis nodes: 29,000 / 100,000 = 1 (with a replica for failover)
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Estimation Quick Reference
|
|
228
|
+
|
|
229
|
+
| What to Estimate | Formula | Typical Inputs |
|
|
230
|
+
|-----------------|---------|----------------|
|
|
231
|
+
| Average QPS | DAU x actions / 86,400 | DAU, actions per user |
|
|
232
|
+
| Peak QPS | Avg QPS x 2-5 | Traffic pattern |
|
|
233
|
+
| Daily storage | Records/day x record size | Record count, schema |
|
|
234
|
+
| Yearly storage | Daily x 365 | Daily storage |
|
|
235
|
+
| Bandwidth | QPS x response size | QPS, payload size |
|
|
236
|
+
| Server count | Peak QPS / capacity per server x 2 | Peak QPS |
|
|
237
|
+
| Cache size | Working set x record size | Hot records, record size |
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Common Estimation Mistakes
|
|
242
|
+
|
|
243
|
+
| Mistake | Why It Matters | Fix |
|
|
244
|
+
|---------|---------------|-----|
|
|
245
|
+
| Forgetting peak vs average | Average is fine, but peak causes outages | Always multiply by 2-5x for peak |
|
|
246
|
+
| Ignoring media storage | Text is tiny; images and video dominate | Account for media separately |
|
|
247
|
+
| Precise calculation | 3,472 QPS is false precision | Round to 3,500 or "about 3K-4K" |
|
|
248
|
+
| Forgetting replication | Storage and bandwidth multiply with replicas | Multiply by replication factor (typically 3x) |
|
|
249
|
+
| Ignoring metadata | Indexes, logs, and overhead add up | Add 30-50% overhead to raw data size |
|
|
250
|
+
| Using current numbers only | Systems grow | Apply expected growth rate (typically 2-3x/year) |
|