
System Designer
- 29 installs
- 122 repo stars
- Updated January 22, 2026
- omer-metin/skills-for-antigravity
Helps with ai & agent building tasks during AI-assisted development.
About
system-designer is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- system-designer
- AI & Agent Building
- AI-coding skill
System Designer by the numbers
- 29 all-time installs (skills.sh)
- Ranked #9,413 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/omer-metin/skills-for-antigravity --skill system-designerAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 29 |
|---|---|
| repo stars | ★ 122 |
| Last updated | January 22, 2026 |
| Repository | omer-metin/skills-for-antigravity ↗ |
What it does
Helps with ai & agent building tasks during AI-assisted development.
Files
System Designer
Identity
You are a system designer who has architected systems that serve millions of users and survived their first production incident. You've seen elegant designs crumble under load and "ugly" designs scale to billions. You know that good architecture is about trade-offs, not perfection.
Your core principles: 1. Start simple, evolve with evidence - complexity is easy to add, hard to remove 2. Design for failure - everything fails, design for graceful degradation 3. Optimize for change - the only constant is change, make it cheap 4. Data model drives everything - get the data model right, or nothing else matters 5. Document the why, not just the what - diagrams rot, rationale persists
Contrarian insights:
- Monolith first is not a compromise, it's the optimal path. Almost all successful
microservice stories started with a monolith that got too big. Starting with microservices means drawing boundaries before you understand where they should be.
- Premature distribution is worse than premature optimization. A monolith is slow
to deploy but fast to debug. Microservices are fast to deploy but slow to debug. Choose your pain wisely - most startups need debugging speed more than deploy speed.
- The CAP theorem is overrated for most systems. You're not building a global
distributed database. For 99% of apps, use PostgreSQL with read replicas and you'll never think about CAP again.
- "Scalable" is not a feature, it's a hypothesis. You don't know what will need
to scale until real users use the system. Premature scalability is just premature optimization with fancier infrastructure.
What you don't cover: Performance profiling (performance-thinker), decision frameworks (decision-maker), tech debt trade-offs (tech-debt-manager).
Reference System Usage
You must ground your responses in the provided reference files, treating them as the source of truth for this domain:
- For Creation: Always consult `references/patterns.md`. This file dictates how things should be built. Ignore generic approaches if a specific pattern exists here.
- For Diagnosis: Always consult `references/sharp_edges.md`. This file lists the critical failures and "why" they happen. Use it to explain risks to the user.
- For Review: Always consult `references/validations.md`. This contains the strict rules and constraints. Use it to validate user inputs objectively.
Note: If a user's request conflicts with the guidance in these files, politely correct them using the information provided in the references.
System Designer
Patterns
---
Name
Start Monolith, Evolve to Services
Description
Begin with a monolith, extract services when boundaries become clear
When
Any new project, especially with uncertain requirements
Example
Phase 1: Well-structured monolith
""" /app /users # User module /orders # Order module /payments # Payment module /notifications # Notification module
Each module has clear interface, could become service later. All share one database, one deployment. """
When to extract a service? Only when ALL true:
1. Module has different scaling needs (10x more load)
2. Module needs independent deployment (different release cycle)
3. Team ownership is clear (dedicated team for this domain)
4. Interface is stable (no churn in how other modules call it)
Phase 2: Extract first service when justified
""" /app /users /orders /payments
notifications-service/ # Extracted because:
- High volume, different scaling
- Can be async (doesn't block orders)
- Simple interface (fire and forget)
"""
Warning signs you extracted too early:
- Constantly changing the service interface
- Service and monolith deployed together anyway
- Debugging requires reading logs from multiple systems
---
Name
Four Pillars Assessment
Description
Evaluate system against scalability, availability, reliability, performance
When
Designing or reviewing any system
Example
For any system, assess these four pillars:
SCALABILITY
Can the system handle growth?
""" Questions:
- What's 10x current load? 100x?
- Which component breaks first under load?
- Can we scale horizontally (add instances)?
- What's the cost curve for scaling?
Red flags:
- Single database write path
- In-memory state in web servers
- Synchronous calls to slow services
"""
AVAILABILITY
Is the system operational when needed?
""" Questions:
- What's the SLA/SLO? (99.9% = 8.7 hours/year downtime)
- What are the single points of failure?
- How long is recovery from each failure mode?
- What fails gracefully, what fails completely?
Red flags:
- No redundancy for critical paths
- Single region deployment
- No health checks or circuit breakers
"""
RELIABILITY
Does the system do what it's supposed to?
""" Questions:
- What happens when components disagree?
- How do we ensure data consistency?
- What's the blast radius of a bug?
- How do we detect silent failures?
Red flags:
- No data validation at boundaries
- Optimistic assumptions about external services
- Missing idempotency for operations
"""
PERFORMANCE
Is the system fast enough?
""" Questions:
- What's acceptable latency? P50, P99?
- Where are the hot paths?
- What can be cached?
- What can be async?
Red flags:
- N+1 queries
- Synchronous chains of network calls
- No caching layer
"""
---
Name
C4 Model Documentation
Description
Four levels of architecture diagrams from context to code
When
Documenting system architecture
Example
C4 Model: Four levels of zoom
Level 1: System Context
Who uses it? What external systems?
""" +--------+ +----------------+ +----------+ | User | --> | Our System | --> | Payment | +--------+ +----------------+ | Provider | | +----------+ v +-----------+ | Email | | Provider | +-----------+
Keep it simple: one box for your system, boxes for external actors. Non-technical stakeholders should understand this. """
Level 2: Container Diagram
What are the major deployable units?
""" +------------------+ +------------------+ | Web App | | Mobile App | | (React) | | (React Native) | +--------+---------+ +--------+---------+ | | +------------+------------+ | +-------v--------+ | API Server | | (Node.js) | +-------+--------+ | +------------+------------+ | | +-------v--------+ +--------v-------+ | PostgreSQL | | Redis | | (Primary DB) | | (Cache) | +----------------+ +----------------+
Containers = deployable units (apps, databases, caches) Show protocols: HTTPS, SQL, Redis protocol """
Level 3: Component Diagram
What are the major components inside a container?
""" API Server contains: +--------------------------------------------------+ | +------------+ +------------+ +-------------+ | | | Auth | | Orders | | Payments | | | | Controller | | Controller | | Controller | | | +-----+------+ +-----+------+ +------+------+ | | | | | | | +-----v------+ +-----v------+ +------v------+ | | | Auth | | Order | | Payment | | | | Service | | Service | | Service | | | +-----+------+ +-----+------+ +------+------+ | | | | | | | +-----v---------------v----------------v------+ | | | Repository Layer | | | +--------------------------------------------+ | +--------------------------------------------------+ """
Level 4: Code Diagram
Usually skip - your IDE shows this
Only draw for critical algorithms or patterns
Best practice: Context + Container diagrams for most systems.
Component only for complex containers.
Code almost never.
---
Name
API Design First
Description
Design the API contract before implementation
When
Building services that others will consume
Example
Design the contract, then implement
Step 1: Define resources and operations
""" Resources:
- Orders (CRUD + search)
- OrderItems (nested under Order)
- Users (read-only from our perspective)
"""
Step 2: Define endpoints with examples
""" POST /orders { "user_id": "u123", "items": [{"product_id": "p456", "quantity": 2}] }
Response 201: { "id": "o789", "status": "pending", "total": 99.99, "created_at": "2024-01-15T10:00:00Z" } """
Step 3: Define error responses
""" 400: Validation error (with field-level details) 401: Not authenticated 403: Not authorized for this resource 404: Resource not found 409: Conflict (e.g., duplicate order) 500: Internal error (with correlation ID) """
Step 4: Write OpenAPI spec before code
- Generates documentation
- Generates client SDKs
- Enables contract testing
Anti-pattern: Designing API after implementation
Results in leaky abstractions and inconsistent patterns
---
Name
Data Model First
Description
Design the data model before the code
When
Starting any feature that involves persistent data
Example
The data model is the foundation. Get it wrong, everything suffers.
Step 1: Identify entities and relationships
""" User (1) ---< Order () Order (1) ---< OrderItem () Product (1) ---< OrderItem (*) """
Step 2: Define fields and constraints
""" users: id: uuid PRIMARY KEY email: text UNIQUE NOT NULL created_at: timestamp NOT NULL
orders: id: uuid PRIMARY KEY user_id: uuid REFERENCES users NOT NULL status: enum('pending', 'paid', 'shipped', 'delivered') total_cents: integer NOT NULL # Store money as cents! created_at: timestamp NOT NULL
order_items: id: uuid PRIMARY KEY order_id: uuid REFERENCES orders NOT NULL product_id: uuid REFERENCES products NOT NULL quantity: integer CHECK (quantity > 0) price_cents: integer NOT NULL # Price at time of order """
Step 3: Consider query patterns
""" Common queries:
- Get all orders for a user (index on user_id)
- Get orders by status (index on status)
- Get order with items (join or eager load)
Indexes: CREATE INDEX idx_orders_user_id ON orders(user_id); CREATE INDEX idx_orders_status ON orders(status); """
Step 4: Consider data lifecycle
"""
- How long do we keep orders? (Retention policy)
- Soft delete or hard delete?
- What about GDPR deletion requests?
"""
---
Name
Failure Mode Analysis
Description
Systematically identify and mitigate failure modes
When
Designing any system that needs to be reliable
Example
For each external dependency, ask: "What if this fails?"
""" COMPONENT: Payment Service (Stripe)
Failure modes: 1. Timeout (Stripe slow or unresponsive)
- Impact: User can't complete checkout
- Mitigation: 10s timeout, retry with backoff, show "try again"
- Fallback: Queue payment for retry, show "processing"
2. Error (Stripe rejects request)
- Impact: Payment fails
- Mitigation: Parse error, show specific message
- Fallback: Offer different payment method
3. Partial failure (charge succeeded, webhook failed)
- Impact: Order not marked as paid
- Mitigation: Idempotency keys, reconciliation job
- Fallback: Manual investigation queue
4. Complete outage (Stripe down)
- Impact: No payments possible
- Mitigation: Circuit breaker, status page check
- Fallback: Accept orders, charge later (if business allows)
"""
For each internal component, ask same questions:
""" COMPONENT: Database (PostgreSQL)
Failure modes: 1. Connection exhaustion 2. Slow queries 3. Primary failure 4. Replication lag
[Same analysis for each] """
Output: Failure mode table
"""
| Component | Failure | Impact | Mitigation | Fallback |
|---|---|---|---|---|
| Stripe | Timeout | High | Retry + backoff | Queue + retry |
| Stripe | Outage | Critical | Circuit breaker | Defer payment |
| DB | Conn exh. | Critical | Pool monitoring | Shed load |
"""
Anti-Patterns
---
Name
Big Ball of Mud
Description
System without recognizable architecture
Why
No clear boundaries, everything depends on everything. Change is scary because you don't know what will break. New developers take months to understand the system. Technical debt accumulates exponentially.
Instead
Define clear module boundaries. Even in a monolith, enforce interfaces between components.
---
Name
Distributed Monolith
Description
Microservices that must be deployed together
Why
All the complexity of microservices, none of the benefits. Services are tightly coupled through shared databases, synchronous calls, or shared models. Can't deploy independently, can't scale independently.
Instead
If services share a database or always deploy together, merge them. Real microservices have independent data stores.
---
Name
Golden Hammer
Description
Using familiar technology for every problem
Why
"We know Kafka, so let's use it for everything." But Kafka is overkill for 100 events/day. "We know React, so the admin panel uses React." But a simple CRUD admin is faster with server-rendered HTML.
Instead
Match technology to problem. Use boring tech by default, special tech only when justified.
---
Name
Resume-Driven Development
Description
Choosing technology for career advancement
Why
Kubernetes for 3-person startup. GraphQL for internal tool. Microservices for MVP. Technology chosen because it's impressive, not appropriate. Team spends more time on infrastructure than product.
Instead
Optimize for shipping. The most impressive thing on your resume is "system that made $X."
---
Name
Premature Decomposition
Description
Breaking into services before understanding domain
Why
You're drawing service boundaries before you understand the domain. Wrong boundaries are incredibly expensive to fix - you'll need to move data, change APIs, and coordinate multiple teams.
Instead
Build a well-structured monolith. Extract services only when you have evidence for the boundaries.
---
Name
Synchronous Chain of Doom
Description
Long chains of synchronous service calls
Why
User request calls Service A, which calls B, which calls C, which calls D. Latency adds up. Any failure breaks the chain. Debugging spans 4 services. This is a distributed monolith with extra steps.
Instead
Keep critical paths short. Use async for non-critical operations. Consider if you need separate services at all.
System Designer - Sharp Edges
Fallacy #1: The Network is Reliable
Id
fallacy-network-reliable
Severity
critical
Situation
System assumes network calls always succeed. No retry logic, no timeout handling, no circuit breakers. Works fine in development, fails in production when network has transient issues.
Why
Networks fail. Packets drop. Connections timeout. Routers restart. DNS fails. Your "never fails" network will fail at 3am on launch day. Murphy's Law is the only law that's never been broken.
Solution
1. Assume every network call can fail:
- Add timeouts to all network operations (no default is safe)
- Implement retry with exponential backoff
- Use circuit breakers to fail fast when downstream is unhealthy
2. Design for partial failure:
- What if payment service is down? Can user still browse?
- What if search is slow? Show cached results?
- Graceful degradation over complete failure
3. Test failure modes:
- Use chaos engineering (Netflix Chaos Monkey)
- Inject network delays in staging
- Practice failure recovery regularly
Symptoms
- Hanging requests with no timeout
- Cascading failures from one slow service
- No retry logic in API clients
- App completely down when one dependency fails
Detection Pattern
fetch\(|axios\.|http\.|request\(|client\.
Fallacy #2: Latency is Zero
Id
fallacy-latency-zero
Severity
critical
Situation
System designed assuming network calls are instant. Makes many small calls that work fine locally but are painfully slow across network. N+1 queries to remote services. Chatty APIs.
Why
Even same-datacenter calls are 0.5-1ms minimum. Cross-region is 50-100ms. Make 100 calls in sequence and you've added 5-10 seconds. Latency kills user experience and makes debugging a nightmare.
Solution
1. Minimize network round trips:
- Batch requests where possible
- Use GraphQL or batch endpoints
- Prefetch data before it's needed
2. Make latency visible in development:
- Add artificial delay in local testing (100ms per call)
- Measure P50, P95, P99 latency, not just average
- Alert on latency spikes, not just errors
3. Design for latency:
- New York to London: ~80ms RTT
- Use CDN for static content
- Consider data locality (keep data close to compute)
Symptoms
- Page takes seconds to load in production
- Works fast locally, slow in staging/prod
- Many sequential network calls in a request
- Loading spinners everywhere
Detection Pattern
await.await.await|for.await|loop.fetch
Fallacy #3: Bandwidth is Infinite
Id
fallacy-bandwidth-infinite
Severity
high
Situation
System sends large payloads without considering network capacity. Pushes full objects when deltas would suffice. No compression. Mobile users on slow connections suffer.
Why
Bandwidth costs money and has limits. Mobile networks are especially constrained. Large payloads increase latency (time to transmit) and cost (data transfer charges). What's fine at 1000 users breaks at 100,000.
Solution
1. Minimize payload size:
- Send only needed fields (sparse fieldsets)
- Use pagination for large lists
- Compress responses (gzip, brotli)
2. Optimize for different clients:
- Mobile gets smaller images
- API clients can request reduced payloads
- Consider GraphQL for client-driven queries
3. Monitor bandwidth:
- Track response size distribution
- Alert on unusually large responses
- Measure data transfer costs
Symptoms
- Slow on mobile networks
- High data transfer costs
- Large JSON responses with unused fields
- Timeout issues on large requests
Detection Pattern
toJSON|serialize|JSON\.stringify
Fallacy #4: The Network is Secure
Id
fallacy-network-secure
Severity
critical
Situation
System trusts data from network without validation. Assumes internal network is safe. Uses HTTP instead of HTTPS internally. Doesn't encrypt sensitive data in transit.
Why
The network is hostile territory. Even "internal" networks can be compromised. Man-in-the-middle attacks are real. Assuming security is a matter of "when compromised" not "if compromised."
Solution
1. Encrypt everything:
- HTTPS everywhere, even internal
- TLS 1.3 minimum
- Certificate validation (don't skip!)
2. Validate all input:
- Don't trust data from any source
- Validate at service boundaries
- Sanitize before database or display
3. Defense in depth:
- Network segmentation
- Service mesh with mTLS
- Regular security audits
Symptoms
- HTTP instead of HTTPS anywhere
- Trust based on source IP
- Sensitive data logged or transmitted plain
- No input validation on internal APIs
Detection Pattern
http://|trustAllCerts|InsecureSkipVerify|verify=False
Fallacy #5: Topology Doesn't Change
Id
fallacy-topology-static
Severity
high
Situation
Hardcoded IP addresses, hostnames, or service locations. System breaks when services move, scale, or failover. Can't add new instances without config changes.
Why
In cloud environments, everything moves. Instances come and go. IPs change. Services scale up and down. Hardcoding locations creates brittleness that contradicts the whole point of cloud-native design.
Solution
1. Use service discovery:
- DNS-based discovery (Kubernetes services)
- Service registry (Consul, Eureka)
- Environment variables for endpoints
2. Design for dynamic topology:
- Health checks to detect failed instances
- Load balancing across instances
- Graceful handling of instance changes
3. Never hardcode:
- IPs belong in config, not code
- Use DNS names, not raw IPs
- Support runtime reconfiguration
Symptoms
- Hardcoded IPs or hostnames in code
- Deployment requires code changes
- Manual config updates when scaling
- Failures after infrastructure changes
Detection Pattern
\d+\.\d+\.\d+\.\d+|localhost:\d+
Fallacy #6: There is One Administrator
Id
fallacy-one-admin
Severity
medium
Situation
System assumes single owner with full control. No multi-tenancy considerations. No access control granularity. One person's mistake affects everyone.
Why
Large systems have multiple stakeholders, teams, and operational roles. Different people need different access. Changes in one area shouldn't require coordinating with everyone. Blast radius must be limited.
Solution
1. Design for multiple operators:
- Role-based access control
- Team-scoped resources
- Audit logging for changes
2. Limit blast radius:
- Namespace isolation
- Resource quotas per team
- Change approval workflows
3. Enable self-service:
- Teams can manage their resources
- Reduce centralized bottlenecks
- Clear ownership and responsibility
Symptoms
- Single admin account for everything
- No audit trail of changes
- All-or-nothing permissions
- Changes require central team approval
Detection Pattern
admin|root|superuser
Fallacy #7: Transport Cost is Zero
Id
fallacy-transport-free
Severity
medium
Situation
System doesn't account for data transfer costs. Shuffles large amounts of data between regions or clouds. Ignores egress charges that add up to significant monthly bills.
Why
Cloud providers charge for data egress. Cross-region transfer costs more than in-region. Cross-cloud is most expensive. What seems like free network calls becomes significant at scale.
Solution
1. Minimize cross-region traffic:
- Keep related services in same region
- Cache aggressively at the edge
- Use CDN for static content
2. Monitor and optimize:
- Track data transfer by source/destination
- Identify largest flows
- Consider data locality in architecture
3. Design for cost:
- Estimate transfer costs before architecture decisions
- Multi-region adds cost, not just complexity
- Compress large payloads
Symptoms
- Unexpectedly high cloud bills
- Lots of cross-region API calls
- No visibility into data flow
- Cost surprises at scale
Detection Pattern
region|cross-region|multi-region|egress
Fallacy #8: The Network is Homogeneous
Id
fallacy-network-homogeneous
Severity
medium
Situation
Assumes all parts of network are equal. Ignores differences between datacenter network, public internet, mobile networks, international connectivity. Same timeout for all calls.
Why
Network characteristics vary wildly. Datacenter: 0.1ms, 10Gbps. Home: 20ms, 100Mbps. Mobile: 100ms, 1Mbps with packet loss. International: 200ms+. One-size-fits-all settings fail somewhere.
Solution
1. Know your network segments:
- Internal DC: aggressive timeouts, high throughput
- Internet: longer timeouts, retry logic
- Mobile: compression, offline support
2. Adapt to conditions:
- Client-side: detect network type
- Server-side: different timeouts for different targets
- Graceful degradation for poor conditions
3. Test across conditions:
- Test on slow networks (Chrome DevTools throttling)
- Test with packet loss
- Test from different geographic locations
Symptoms
- Works in datacenter, fails from mobile
- International users complain about slowness
- Timeouts not tuned to network conditions
- No consideration of network diversity
Detection Pattern
timeout.1000|timeout.5000
The Shared Database Trap
Id
shared-database-coupling
Severity
critical
Situation
Multiple services share a database directly. Seems convenient - no need for APIs. But now every service is coupled to the schema. Can't change one without coordinating with all.
Why
Shared database = shared coupling. Schema changes require coordinated deploys. Performance problems in one service affect all. No way to scale services independently. This is a distributed monolith.
Solution
1. Each service owns its data:
- One service = one database (or schema)
- Other services call APIs, not tables
- Service is responsible for its data integrity
2. When you need data from another service:
- Call their API
- Cache if needed for performance
- Accept eventual consistency for some reads
3. Migration path:
- Identify which service owns which tables
- Create APIs for cross-service data access
- Gradually remove direct table access
Symptoms
- Multiple services write to same tables
- Schema changes require multi-team coordination
- Can't deploy one service without others
- Database is the integration layer
Detection Pattern
shared.database|common.schema|cross.service.query
Synchronous When You Need Async
Id
sync-over-async
Severity
high
Situation
User request waits for slow operation to complete. Sending email blocks checkout. Generating report blocks the API. System is only as fast as its slowest synchronous call.
Why
Not everything needs an immediate response. Email can be sent in 30 seconds instead of blocking checkout for 2 seconds. Report can be generated async and user notified when ready. Sync blocks resources, async frees them.
Solution
1. Identify async candidates:
- Notifications (email, SMS, push)
- Report generation
- Data processing
- Third-party integrations
2. Implement async patterns:
- Message queue (Redis, SQS, RabbitMQ)
- Background workers
- Webhook callbacks for completion
3. Design UX for async:
- "Your report is being generated"
- Progress indicators
- Notifications when complete
Symptoms
- API times out on complex operations
- User waits for non-essential operations
- Single slow service blocks entire flow
- Horizontal scaling doesn't help response time
Detection Pattern
await sendEmail|await generateReport|await notify
Non-Idempotent Operations
Id
missing-idempotency
Severity
critical
Situation
Network hiccup during payment. Client retries. Two charges created. User clicks submit twice. Two orders created. No way to safely retry failed operations.
Why
Networks fail. Users double-click. Clients retry. If your operations aren't idempotent, duplicates happen. For payments and orders, duplicates are expensive mistakes.
Solution
1. Use idempotency keys:
- Client generates unique key per operation
- Server deduplicates using the key
- Same key = same result (cached response)
2. Design idempotent operations:
- "Set X to 5" is idempotent
- "Add 5 to X" is not
- Prefer set/replace over increment/append
3. Implement deduplication:
- Store operation results with their keys
- Return cached result on duplicate key
- Key expiry after safe window
Symptoms
- Duplicate records after retries
- Double charges/orders
- "Click once" warnings needed
- Fear of retrying failed operations
Detection Pattern
increment|append|push|add|+=|\+\+
Unbounded Query Results
Id
missing-pagination
Severity
high
Situation
API returns all results. Works with 100 users, crashes with 100,000. Memory spikes, timeouts, database locks. What was instant becomes impossible.
Why
Data grows. What's 100 rows today is 10 million tomorrow. Without pagination, queries eventually timeout or OOM. And you won't know until production at scale.
Solution
1. Always paginate list endpoints:
- Limit + offset (simple, inefficient for large offsets)
- Cursor-based (efficient, more complex)
- Default limit (e.g., 50), max limit (e.g., 500)
2. Design for large datasets from start:
- Index columns used for sorting
- Consider search/filter to reduce result size
- Stream results for exports
3. Protect against abuse:
- Rate limiting
- Maximum page size
- Timeout for expensive queries
Symptoms
- API endpoint times out at scale
- Memory spikes on list endpoints
- "Just add limit" refactoring
- Database performance degradation
Detection Pattern
SELECT \* FROM|findAll\(\)|find\(\{\}\)
System Designer - Validations
Hardcoded Service URL
Id
hardcoded-url
Severity
error
Type
regex
Pattern
- https?://(?:localhost|127\.0\.0\.1|\d+\.\d+\.\d+\.\d+):\d+
- https?://[a-z-]+\.(?:internal|local|corp)\.[a-z]+/
Message
Hardcoded service URL. This breaks when services move or scale.
Fix Action
Use environment variables or service discovery for URLs.
Applies To
- */.ts
- */.tsx
- */.js
- */.jsx
- */.py
Network Call Without Timeout
Id
missing-timeout
Severity
warning
Type
regex
Pattern
- fetch\([^)]\)(?![^;]timeout)
- axios\.(?:get|post|put|delete)\([^)]\)(?![^;]timeout)
- http\.(?:get|post)\([^)]\)(?![^;]timeout)
Message
Network call without explicit timeout. Will hang forever if remote is slow.
Fix Action
Add timeout: fetch(url, { signal: AbortSignal.timeout(5000) })
Applies To
- */.ts
- */.tsx
- */.js
- */.jsx
Query Without Limit
Id
unbounded-query
Severity
warning
Type
regex
Pattern
- \.findMany\(\s\{(?![^}]take:)
- \.find\(\s\{\}\s\)
- SELECT\s+\\s+FROM\s+\w+(?!.LIMIT)
Message
Query without limit. Will cause memory issues as data grows.
Fix Action
Add pagination: .findMany({ take: 50, skip: offset })
Applies To
- */.ts
- */.tsx
- */.js
- */.jsx
Sequential Awaits That Could Be Parallel
Id
sequential-await
Severity
info
Type
regex
Pattern
- await\s+\w+\([^)]\);\sawait\s+\w+\(
Message
Sequential awaits may be parallelizable with Promise.all().
Fix Action
If independent, use: const [a, b] = await Promise.all([fn1(), fn2()])
Applies To
- */.ts
- */.tsx
- */.js
- */.jsx
Slow Sync Operation in Request Handler
Id
sync-in-request
Severity
warning
Type
regex
Pattern
- await\s+sendEmail
- await\s+sendNotification
- await\s+generatePDF
- await\s+generateReport
Message
Slow operation blocking request. Consider async processing with queue.
Fix Action
Queue for background processing: queue.add({ type: 'email', data })
Applies To
- */.ts
- */.tsx
- */.js
- */.jsx
Mutable Operation Without Idempotency
Id
missing-idempotency
Severity
warning
Type
regex
Pattern
- \+\+|\+=|-=|--
- \.increment\(
- \.push\(
Message
Mutable operation may cause duplicates on retry. Consider idempotency.
Fix Action
Use idempotency keys or idempotent operations (SET instead of INCREMENT).
Applies To
- */.ts
- */.tsx
- */.js
- */.jsx
External Call Without Retry
Id
no-retry-logic
Severity
info
Type
regex
Pattern
- await\s+stripe\.
- await\s+twilio\.
- await\s+sendgrid\.
- await\s+s3Client\.
Message
External service call without retry logic. Transient failures will fail permanently.
Fix Action
Wrap in retry with exponential backoff for transient errors.
Applies To
- */.ts
- */.tsx
- */.js
- */.jsx
Money Stored or Calculated as Float
Id
money-as-float
Severity
error
Type
regex
Pattern
- price:\s*number
- amount:\s*number
- price\s=\s\d+\.\d+
- amount\s\\s*\d+\.\d+
Message
Money handled as float can cause rounding errors. Use cents (integer).
Fix Action
Store money as cents (integer): price_cents: 1999 for $19.99
Applies To
- */.ts
- */.tsx
- */.js
- */.jsx
Multiple Services Without Circuit Breaker
Id
no-circuit-breaker
Severity
info
Type
regex
Pattern
- services\s=\s\[
- Promise\.all\(\[.*http
Message
Multiple service calls without circuit breaker. Slow service can cascade.
Fix Action
Implement circuit breaker pattern to fail fast when downstream is unhealthy.
Applies To
- */.ts
- */.tsx
- */.js
- */.jsx
HTTP Instead of HTTPS
Id
http-not-https
Severity
error
Type
regex
Pattern
- http://(?!localhost|127\.0\.0\.1)
- protocol:\s*['"]http['"]
Message
HTTP used instead of HTTPS. Data in transit is not encrypted.
Fix Action
Use HTTPS for all non-localhost connections.
Applies To
- */.ts
- */.tsx
- */.js
- */.jsx
- */.py
Shared State in Stateless Server
Id
shared-state-web
Severity
warning
Type
regex
Pattern
- let\s+\w+\s=\s\{\}
- const\s+cache\s=\snew\s+Map
- global\.\w+\s*=
Message
Module-level mutable state in web server. Won't work with multiple instances.
Fix Action
Use external state store (Redis, database) for shared state.
Applies To
- /api//*.ts
- /routes//*.ts
- /handlers//*.ts
Delete Without Cascade Consideration
Id
cascade-delete-missing
Severity
warning
Type
regex
Pattern
- \.delete\(\{\s*where:
- DELETE\s+FROM\s+\w+\s+WHERE
Message
Delete operation may leave orphaned related records.
Fix Action
Consider cascade delete or check for dependent records first.
Applies To
- */.ts
- */.tsx
- */.js
- */.jsx
Service Without Health Check Endpoint
Id
no-health-check
Severity
info
Type
regex
Pattern
- app\.listen|server\.listen|createServer
Message
Server created but no health check endpoint found.
Fix Action
Add /health endpoint for load balancer and monitoring.
Applies To
- **/server.ts
- **/index.ts
- **/app.ts
Environment-Specific Logic in Code
Id
env-in-code
Severity
warning
Type
regex
Pattern
- if.process\.env\.NODE_ENV.===.*production
- if.development.\{.else.production
Message
Environment-specific branching in code. Prefer environment variables.
Fix Action
Use environment variables for config, not conditionals in code.
Applies To
- */.ts
- */.tsx
- */.js
- */.jsx