Slopapalooza

What it is

The Infinite Patch Spiral is repeated symptom-fixing without checking the assumption behind the failures. AI patches the reported case, another case breaks, and the next prompt adds another exception. Frequent edits alone do not prove the design is wrong. The warning is that each fix depends on preserving a workaround nobody can explain.

How a local fix becomes a design problem

In an illustrative order importer, a retry creates a duplicate order. The first fix adds a lookup before insertion. Two workers then perform the lookup at the same time, both find nothing, and both insert. The next fix adds a lock inside one worker process. It passes a local test but does not coordinate two separate workers. A retry delay reduces collisions in the test run, and the ticket closes again. No test forced both workers past the lookup before either could insert.

Each fix coordinates less than the full set of writers. The useful question is which boundary can enforce the rule for all of them. If one source order must map to one imported order, the database can enforce a unique, non-null key such as source system plus source order ID. PostgreSQL’s constraint documentation describes uniqueness over a group of columns. The importer still needs defined conflict handling; a constraint violation is not automatically a successful retry.

Why it keeps happening

“Fix this failing test” gives the agent a narrow finish line. It may never inspect other writers, the transaction boundary, or the requirement behind the test. AI can investigate all of those when the task includes them. The failure is accepting a local repair as evidence that the broader problem is understood.

Soon a reviewer cannot tell which branches implement business rules and which compensate for earlier patches. Removing any branch feels risky, so every new fix works around it. Cheap edits keep an expensive design on life support.

How to get out of the spiral

Start with the failure history, not a rewrite. Have AI trace the related commits, callers, and tests, then state a hypothesis that can be disproved. For the importer, use two database connections and a test barrier that holds each worker after its lookup. Release them together and check the resulting orders. This forces the race instead of hoping a stress test happens to hit it. Running the import twice in sequence checks retry behavior, not concurrent insertion.

A narrow patch may be the right incident containment. Record what it prevents and what remains unresolved. Repeated fixes can also reflect genuinely new requirements. Neither a busy file nor a third bug earns an automatic architecture rewrite.

The serious team fix

  1. Put the rule at the shared boundary. For the importer, reconcile existing duplicates before adding the constraint. Make both key fields required, and define whether a repeated source ID means retrying creation or updating an existing order. An unchanged retry should return the existing result; compare the stable request identity and relevant original input, not an order whose status may have changed since creation. A legitimate amendment needs its own update rule. Handle the expected uniqueness conflict specifically rather than treating every database error as “already imported.”
  2. Cover the consequence beyond the row. One order row does not prevent two confirmation emails. Trace which writer emits events or calls other services. Where the downstream service supports deduplication, reuse a stable operation identifier on retries and account for its retention window. Otherwise define how an uncertain result is reconciled before repeating the action. Test concurrent delivery and a lost response after commit, including the downstream work.
  3. Retire the workarounds deliberately. Remove the delay and process-local lock only after checking whether they protect anything else. Keep regression cases for the original failures. The repair should explain why those failures can no longer occur, not merely make them less likely in this afternoon’s test.

Related anti-patterns

Back to all anti-patterns