reviewer-harness 1.7.0 → 1.8.0
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.
- package/package.json +1 -1
- package/skills/backend-performance.md +66 -0
- package/skills/devops-basics.md +66 -0
package/package.json
CHANGED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-performance
|
|
3
|
+
description: 10 backend performance rules distilled from nodebestpractices (105k stars) and system-design-primer — event loop, caching, idempotency, backpressure, and the latency numbers that tell you what's actually slow.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Skill: backend-performance
|
|
7
|
+
|
|
8
|
+
When to use: building or reviewing any backend — API endpoints, database queries, or background jobs. Apply when the app feels slow, hangs, or breaks under repeated requests.
|
|
9
|
+
|
|
10
|
+
Every rule below is distilled from a reputable open-source repo (cited per rule). If a rule doesn't apply, say why.
|
|
11
|
+
|
|
12
|
+
### Don't block the machine
|
|
13
|
+
1. **Never block the event loop.** Node runs your code on a single thread — one slow synchronous operation (huge JSON parse, giant loop, unsafe regex) stalls every request behind it. Keep per-request work small; offload CPU-heavy jobs to a worker or separate service.
|
|
14
|
+
*Source: goldbergyoni/nodebestpractices — `sections/performance/block-loop.md`*
|
|
15
|
+
|
|
16
|
+
2. **Prefer native methods over utility libraries.** Native V8 methods (Array.map, String.indexOf) run roughly 50% faster than Lodash/Underscore equivalents — benchmarks show Lodash averaging ~146% more time per operation. If the platform already does it, drop the dependency. Enforce with `eslint-plugin-you-dont-need-lodash-underscore`.
|
|
17
|
+
*Source: goldbergyoni/nodebestpractices — `sections/performance/nativeoverutil.md`*
|
|
18
|
+
|
|
19
|
+
### Cache deliberately
|
|
20
|
+
3. **Put a cache in front of the database.** RAM reads take ~100ns; an SSD random read ~150µs; an HDD seek ~10ms. An in-memory cache (Redis, Memcached) absorbs traffic spikes so the database doesn't take the hit directly. Use an eviction policy like LRU to keep hot entries and drop cold ones.
|
|
21
|
+
*Source: donnemartin/system-design-primer — `README.md`, "Cache" section*
|
|
22
|
+
|
|
23
|
+
4. **Use cache-aside with a TTL — and know its tradeoffs.** Simplest pattern: check cache first; on miss, load from DB, store, return (lazy loading — only requested data gets cached). Every miss costs three trips, and cached data goes stale — mitigate with a time-to-live that forces refresh. Alternatives: write-through (never stale, slow writes) and write-behind (fast writes, data loss if cache dies).
|
|
24
|
+
*Source: donnemartin/system-design-primer — `README.md`, "Cache-aside" sections*
|
|
25
|
+
|
|
26
|
+
### Design for failure
|
|
27
|
+
5. **Build retries on idempotent operations.** GET, PUT, and DELETE can be repeated safely; POST and PATCH cannot — a retried POST creates duplicates. Any write endpoint that might be retried (network replay, double-click) needs an explicit idempotency mechanism such as idempotency keys. The protocol won't save you on POST.
|
|
28
|
+
*Source: donnemartin/system-design-primer — `README.md`, HTTP verb table*
|
|
29
|
+
|
|
30
|
+
6. **Apply backpressure; retry with exponential backoff.** When a work queue outgrows memory, throughput collapses — cap the queue, reject overflow with HTTP 503, and let clients retry later. Retries must use growing delays (not immediate hammering), or the retry storm finishes off the struggling server.
|
|
31
|
+
*Source: donnemartin/system-design-primer — `README.md`, "Asynchronism" section*
|
|
32
|
+
|
|
33
|
+
7. **Pool expensive connections.** Opening a TCP connection per request (app → database, server → cache) burns memory and setup cost each time. Reuse a bounded pool instead. Size it deliberately — too small starves throughput, too large wastes memory.
|
|
34
|
+
*Source: donnemartin/system-design-primer — `README.md`, "Communication" section*
|
|
35
|
+
|
|
36
|
+
### Measure, don't guess
|
|
37
|
+
8. **Know your latency numbers.** L1 cache ~0.5ns, RAM ~100ns, SSD ~150µs, datacenter round trip ~500µs, HDD seek ~10ms, cross-continent ~150ms. "The database is slow" usually means "we're doing disk or network round trips we could avoid." Measure first, then attack the biggest number.
|
|
38
|
+
*Source: donnemartin/system-design-primer — `README.md`, "Latency numbers every programmer should know"*
|
|
39
|
+
|
|
40
|
+
9. **Distinguish performance from scalability problems.** Slow for a single user = performance problem (fix the code/queries). Fast for one user but slow under load = scalability problem (add caching, pooling, capacity). The fix differs — diagnose before prescribing. Target: maximal throughput with acceptable latency.
|
|
41
|
+
*Source: donnemartin/system-design-primer — `README.md`, "Performance vs scalability"*
|
|
42
|
+
|
|
43
|
+
10. **Watch the four golden signals.** Error rate (users feel it immediately), latency (directly affects business), throughput (gives context to the other two), and saturation (90% CPU = no headroom). Node-specific: keep process RAM under ~1.4GB, track errors per minute and restarts.
|
|
44
|
+
*Source: goldbergyoni/nodebestpractices — `sections/production/monitoring.md`*
|
|
45
|
+
|
|
46
|
+
### Also apply (general practice, beyond these repos)
|
|
47
|
+
- **Kill N+1 queries** — never query inside a loop; fetch related data with JOIN or `IN (...)`.
|
|
48
|
+
- **Index hot columns** — foreign keys, `WHERE` and `ORDER BY` columns; verify with `EXPLAIN`.
|
|
49
|
+
- **Set timeouts on every external call** — fail fast instead of hanging forever.
|
|
50
|
+
- **Paginate large lists** — never return "all rows"; cap page size.
|
|
51
|
+
|
|
52
|
+
### Quick check before shipping
|
|
53
|
+
- [ ] No synchronous heavy work on the request path (event loop stays free)
|
|
54
|
+
- [ ] No Lodash where a native method does the job
|
|
55
|
+
- [ ] Repeated reads are cached with a TTL and an invalidation plan
|
|
56
|
+
- [ ] Write endpoints are idempotent or carry idempotency keys
|
|
57
|
+
- [ ] Retries use backoff; queues have caps with 503 on overflow
|
|
58
|
+
- [ ] Connections come from a sized pool, released on every path
|
|
59
|
+
- [ ] Slowest path measured against the latency scale — biggest number attacked first
|
|
60
|
+
- [ ] Four golden signals are tracked (errors, latency, throughput, saturation)
|
|
61
|
+
|
|
62
|
+
### Learn more (official sources)
|
|
63
|
+
- Node.js best practices (105k stars): https://github.com/goldbergyoni/nodebestpractices
|
|
64
|
+
- System design primer: https://github.com/donnemartin/system-design-primer
|
|
65
|
+
- Don't block the event loop (Node.js docs): https://nodejs.org/en/docs/guides/dont-block-the-event-loop/
|
|
66
|
+
- Latency numbers: https://github.com/donnemartin/system-design-primer#latency-numbers-every-programmer-should-know
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: devops-basics
|
|
3
|
+
description: 10 DevOps rules distilled from nodebestpractices (105k stars) — Docker images, graceful shutdown, health checks, smart logging, and memory guards. Ship reliably instead of deploying by hand and hoping.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Skill: devops-basics
|
|
7
|
+
|
|
8
|
+
When to use: containerizing an app, setting up deployment, adding observability, or reviewing anything that ships to production. Apply when deploys are manual, scary, or "works on my machine" only.
|
|
9
|
+
|
|
10
|
+
Every rule below is distilled from a reputable open-source repo (cited per rule). If a rule doesn't apply, say why.
|
|
11
|
+
|
|
12
|
+
### Build lean images
|
|
13
|
+
1. **Ship small base images.** A full Node.js image (~345MB) is roughly 10× the weight of its Alpine variant (~39MB); Slim is similarly tiny (~38MB). Smaller images pull faster, start faster, use less storage, and shrink the attack surface — fewer packages, fewer vulnerabilities. If the minimal image lacks build tools, install them in a separate build stage.
|
|
14
|
+
*Source: goldbergyoni/nodebestpractices — `sections/docker/smaller_base_images.md`*
|
|
15
|
+
|
|
16
|
+
2. **Prefer COPY over ADD; keep builds reproducible.** COPY only copies local files; ADD can silently fetch remote binaries — a supply-chain risk. Never run `apt-get update` inside the build: it produces a different image every time and needs elevated privileges. Use base images that their maintainers update frequently instead.
|
|
17
|
+
*Source: goldbergyoni/nodebestpractices — `sections/docker/generic-tips.md`*
|
|
18
|
+
|
|
19
|
+
3. **Run unprivileged and inspect what you ship.** Privileged containers have root-equivalent power over the host — almost never needed; use the `node` user baked into official Node images. Builds leak secrets and bloat (leftover files, dev dependencies) — inspect the final image with a tool like Dive to catch both.
|
|
20
|
+
*Source: goldbergyoni/nodebestpractices — `sections/docker/generic-tips.md`*
|
|
21
|
+
|
|
22
|
+
### Shut down like a professional
|
|
23
|
+
4. **Handle SIGTERM gracefully — don't let npm swallow it.** Orchestrators kill containers constantly (deploys, rescheduling, scaling) with SIGTERM and a ~30-second grace period. The app must: stop accepting new requests, finish in-flight ones, release resources, log, then exit. Anti-pattern: `CMD ["npm", "start"]` — npm sits between the signal and Node, so Node never receives it. Fix: `CMD ["node", "index.js"]` or run under Tini.
|
|
24
|
+
*Source: goldbergyoni/nodebestpractices — `sections/docker/graceful-shutdown.md`*
|
|
25
|
+
|
|
26
|
+
5. **Expose health checks so the platform routes around sickness.** The load balancer needs to know "don't send me traffic" during shutdown and "I'm broken, restart me" during failures. A `/health` (liveness) endpoint answers "am I alive?"; a readiness check answers "am I ready to serve?" Keep them lightweight — a health check that does heavy work becomes the outage.
|
|
27
|
+
*Source: goldbergyoni/nodebestpractices — `sections/docker/graceful-shutdown.md`*
|
|
28
|
+
|
|
29
|
+
6. **Keep a private ops endpoint — locked to admins.** Some diagnostics are app-specific (heap dumps, memory reports) and generic monitoring tools can't reach them. Expose them on a dedicated maintenance endpoint, but restrict it to admins — it can become a DDoS target. Use professional monitoring for the standard stuff; the custom endpoint is for the rest.
|
|
30
|
+
*Source: goldbergyoni/nodebestpractices — `sections/production/createmaintenanceendpoint.md`*
|
|
31
|
+
|
|
32
|
+
### Log so you can debug later
|
|
33
|
+
7. **Tag every log line with a request ID.** A production log is thousands of interleaved requests — without a shared ID you can't reconstruct one user's flow from the noise. Assign a unique transaction ID per request, attach it to every log statement, and propagate it downstream via an `x-transaction-id` header. In Node this needs AsyncLocalStorage (v14+) or a helper like cls-rtracer.
|
|
34
|
+
*Source: goldbergyoni/nodebestpractices — `sections/production/assigntransactionid.md`*
|
|
35
|
+
|
|
36
|
+
8. **Log structured, with context.** Format logs as JSON with timestamps, request IDs, user IDs, and operation types — readable by humans and machines. Log at transaction start and end so you can trace errors and spot the slowest endpoints. Never log secrets. If you can't reconstruct what happened from the logs, they're decoration.
|
|
37
|
+
*Source: goldbergyoni/nodebestpractices — `sections/production/smartlogging.md`*
|
|
38
|
+
|
|
39
|
+
### Guard the runtime
|
|
40
|
+
9. **Cap memory and hunt leaks.** Node's default heap target is ~1.5GB — on smaller machines cap it explicitly (e.g. `node --max_old_space_size=400 server.js`), because V8's stop-the-world garbage collector gets expensive near the limit. Prevent leaks: avoid globals, stream data instead of buffering it, scope with let/const. Find leaks by diffing heap dumps taken apart in time.
|
|
41
|
+
*Source: goldbergyoni/nodebestpractices — `sections/production/measurememory.md`*
|
|
42
|
+
|
|
43
|
+
10. **Monitor the four golden signals; save APM for scale.** Track error rate, latency, throughput, and saturation — plus Node specifics (process RAM, errors per minute, restarts). Full APM suites trace transactions end-to-end but carry a price tag: justified for large complex systems, overkill for a small app where the four signals plus good logs suffice.
|
|
44
|
+
*Source: goldbergyoni/nodebestpractices — `sections/production/monitoring.md`, `sections/production/apmproducts.md`*
|
|
45
|
+
|
|
46
|
+
### Also apply (general practice, beyond these repos)
|
|
47
|
+
- **Automate build + test on every push (CI)** — red build blocks the merge; nobody merges without green checks.
|
|
48
|
+
- **Version your API explicitly** (`/v1`, `/v2`) with semantic versioning; deprecate with a sunset date, never silently change shapes.
|
|
49
|
+
- **Migrate the database, don't hand-edit it** — versioned migration files, tested before production, reversible where possible.
|
|
50
|
+
- **Back up on a schedule and test the restore** — an untested backup is a hope, not a backup.
|
|
51
|
+
|
|
52
|
+
### Quick check before shipping
|
|
53
|
+
- [ ] Base image is Alpine/Slim (~40MB), built with COPY, no `apt-get update` inside
|
|
54
|
+
- [ ] Container runs as non-root user; final image inspected (no secrets, no bloat)
|
|
55
|
+
- [ ] App handles SIGTERM: drains requests, releases resources, exits cleanly
|
|
56
|
+
- [ ] `/health` endpoint exists, is lightweight, and is wired to the platform
|
|
57
|
+
- [ ] Every log line carries a request/transaction ID, propagated downstream
|
|
58
|
+
- [ ] Logs are JSON with timestamps and context; no secrets logged
|
|
59
|
+
- [ ] Memory is capped for the machine size; leak-hunting path is known
|
|
60
|
+
- [ ] Four golden signals are monitored with alerts on user-facing symptoms
|
|
61
|
+
|
|
62
|
+
### Learn more (official sources)
|
|
63
|
+
- Node.js best practices (105k stars): https://github.com/goldbergyoni/nodebestpractices
|
|
64
|
+
- Docker best practices: https://docs.docker.com/build/building/best-practices/
|
|
65
|
+
- Graceful shutdown in Node: https://github.com/goldbergyoni/nodebestpractices/tree/master/sections/docker
|
|
66
|
+
- Semantic versioning: https://semver.org/
|