# Anti-Patterns > A catalog of violations. Each entry names the principle it breaches. Use this to recognize and reject patterns on sight. ## How to Use When you see a pattern listed here, it is a defect. Cite the principle it violates and require a fix. These are not "to be reviewed later"; they are rejected on sight. ## Core Anti-Patterns (C1–C8) | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | Code that "mostly works" | C1 Correctness | Mostly correct is incorrect | | `function doStuff()` | C2 Clarity | Name reveals nothing | | A 500-line function | C3 Simplicity | Complexity is a liability | | Config in a distant repo, read silently | C4 Locality | Coupling you cannot see | | A migration with no `down` | C5 Reversibility | Irreversible bet | | A component reading global state implicitly | C6 Composability | Hidden dependency | | A service with no logs | C7 Observability | Cannot debug what you cannot see | | Loading all records into memory | C8 Economy | Unbounded = OOM | ## Domain Anti-Patterns ### UI/UX | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | Image without `alt` | P2 Accessibility | Disqualifying | | "Delete" with no confirmation | P5 Forgiveness | Irreversible surprise | | `color: #3b82f6` in a component | P8 Consistency (via tokens) | Bypasses design system | | "Submit" on a delete button | P3 Clarity | Wrong verb | | Layout shift on image load | P7 Hierarchy / CLS | Visual instability | ### API | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | `/getUsers` (verb in URL) | P2 Clarity | Resources are nouns | | 200 with an error body | P9 Error Transparency | Status code lies | | 500 with a stack trace | P8 Security, P9 | Information leak | | No `Idempotency-Key` on a POST | P6 Idempotency | Retry is unsafe | | 10MB response by default | P7 Performance | Unbounded payload | ### Security | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | `eval()` of any string | P4, P5 | Code injection | | Hardcoded API key in source | P9 Secret Hygiene | Committed secret | | `catch (e) {}` (swallow) | P7, P8 | Silent failure, fail-open | | `md5` for password hashing | P6 Crypto | Broken primitive | | Open CORS `*` in production | P1, P10 | Zero trust violated | | `chmod 777` | P2 Least Privilege | Maximum privilege | | Logging the request body | P9 Secret Hygiene | Token leak | ### Data | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | `VARCHAR` for a UUID | P7 Type Fidelity | Wrong type | | No FOREIGN KEY | P3, P9 | Unenforced relationship | | `FLOAT` for money | P7, P1 | Floating point error | | `is_deleted` without filtering | P8 Lifecycle | Soft-delete leak | | `SELECT *` | P10 Performance | Unbounded columns | ### Testing | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | Test that cannot fail | P10 No Test Theater | Not a test | | `Date.now()` in a fixture | P3 Determinism | Flaky | | Shared fixture mutated across tests | P2 Independence | Order-dependent | | 500 e2e tests, 50 unit | P4 Fast Feedback | Inverted pyramid | | `name: "test"` fixture | P7 Realism | Hides bugs | ### Performance | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | N+1 query in a loop | P3 Complexity | O(N) queries | | No timeout on HTTP call | P4, P8 (concurrency) | Hang forever | | Cache with no invalidation | P5 Caching | Stale forever | | Unbounded in-memory sort | P4 Resource Bounds | OOM | | Optimization without measurement | P1 Measure First | Guesswork | ### Observability | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | `console.log("here")` | P1 Structured | Not queryable | | `user_id` as a metric label | P4 Cardinality | Unbounded bill | | Average latency only | P8 SLO | Hides the tail | | No `trace_id` propagation | P2 Correlation | Cannot trace | | Logs without `request_id` | P3 Context | No correlation | ### Errors | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | `catch (e) { return null }` | P2 Fail Loudly | Silent failure | | `throw new Error("error")` | P3 Fail Specifically | Generic | | `return null` for "not found" | P1 Errors are Data | Conflates absence with error | | Retry without backoff | P5, P8 | Retry storm | | `throw` in a recovery path | P6 | Fail fast in wrong place | ### Documentation | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | Doc with no examples | P3 Examples | Incomplete | | Stale doc (wrong, not updated) | P4 Currency | Worse than no doc | | Unlisted doc (not in MANIFEST) | (framework rule) | Not part of framework | | No audience statement | P2 Audience | Who is this for? | ### Concurrency | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | Shared mutable state, no lock | P1 Immutability | Race condition | | Unbounded queue | P9 Bounded Queues | OOM | | `channel.send()` with no timeout | P8 Timeout | Hang | | Mutex held across I/O | P3 Lock Scope | Lock too long | | Spawned work with no cancellation | P7 Cancellation | Orphaned work | ### DevOps | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | Manual deploy script | P2 Automation | Not repeatable | | No rollback path | P4 Rollback | Irreversible deploy | | Big-bang deploy | P5 Progressive | All-or-nothing | | Rebuild per environment | P7 Immutability | Different artifacts | | Snowflake server | P1, P6 | Not reproducible | ## Cross-Cutting Anti-Patterns | Anti-Pattern | Breaches | Why | |--------------|----------|-----| | "I'll add tests later" | C1 (no proof of correctness) | Later never comes | | "It's just a prototype" | C5 (irreversible by default) | Prototypes go to prod | | Copy-paste code | C6 (no composition) | Bug duplicated | | God object | C3, C6 | One thing, many things | | Leaky abstraction | C6, C2 | Hidden coupling |