Build1 publisher3 min readPublished
Wiring the breaker_machines gem into a Rails app took an afternoon. Making a circuit actually open took a week. The decisions that survive are about which Redis database holds state and which integration sets its own threshold.
The Engineer · Build desk

Compiled by The EngineerSomething wrong?How this is made
Replicate's threshold is the number to stare at. The Vertex template opens on three failures inside 60 seconds [12]. Replicate instead gets five inside an hour, because the integration takes roughly one invocation a day and, in the author's words, a one-minute window is statistically unreachable [13]. Run the rate: one call a day is about 0.0007 calls in any given minute [1], and the default wants three failures in that window. Widen to an hour and the expectation is still only about 0.04 calls [2], against a threshold of five.
A breaker on a dependency that quiet cannot open on organic traffic. It opens when something bunches calls together. In a Rails app the usual bunching agent is the retry: a Sidekiq job fails, retries, hammers the dead service, ties up a worker, and the queue backs up behind it [3]. So the threshold on a low-traffic integration is calibrated against retry behaviour and against the provider's rate limit, which the author says produces short failure clusters more often than a real outage does [13]. "The thresholds describe the service, not a global default" [14] is the load-bearing sentence in the write-up.
The four-circuits decision reads the same way. Four services call the same gemini-2.5-flash model, so one shared circuit is the tidier configuration and they genuinely share fate [8]. The design note gives three reasons for splitting them, and the third decides it: a false-positive open on MissingItemDetector returns an empty array, while a false-positive open on OutfitSuggestionService blocks a paywalled flow [11]. Merging the circuits merges the failure counts, and it also sets the group's false-positive cost to that of its most expensive member. The April 23 incident came out of ImageAnalysisJob under load [9], which is precisely the noisy neighbour a shared circuit would have let degrade outfit suggestions and trip planning by contagion [9].
Then the Redis choice, which is the part most likely to bite someone copying this. State has to be visible to web dynos and Sidekiq workers alike, so it lives in Redis, and specifically in db 1 rather than db 0 alongside Rails.cache [15]. Rails.cache.clear and Rack::Attack key churn wipe db 0 wholesale, and losing breaker state during an outage re-arms the breaker mid-incident and lets traffic stampede a service that is already down [16]. The key namespace does not save you: ActiveSupport's :redis_cache_store namespaces keys and does not isolate them [17].
For any of these settings to transfer, the feature needs enough volume that three failures in 60 seconds is reachable, and a provider that recovers on roughly the 30-second reset the template assumes [12]. The same declaration carries jitter: 0.25 [12], and the material does not say how the gem applies it, so treat that one as unverified.
The write-up is titled for having had to patch the gem twice [18], and the available text stops inside the Redis section without naming either patch [18]. The wiring took an afternoon; the week went to everything the DSL does not cover [6][7]. Two things here are reusable even without the patches: keep breaker state out of the database your cache clears, and let each integration's call rate set its own window.
Ranked by verification strength, evidence, and original report placement.
In OutfitMaker, outfit suggestions, wardrobe image analysis, missing-item detection and trip planning all call Gemini through Vertex AI.
The Look Preview feature calls a second Google API for image generation, product images come from Replicate, and affiliate suggestions come from Amazon via RapidAPI.
The author describes the Rails failure mode without breakers: a Sidekiq job retries, hammers the dead service, ties up a worker, the retry queue backs up, and the failure spreads to features unrelated to the broken provider.
A circuit breaker is described as a small state machine in front of an external call: after a set number of failures inside a time window it opens and calls fail instantly, then after a cooldown it goes half-open, lets one call through, and either closes or opens again.
Circuit breakers shipped across all six integrations in two phases in early May 2026: Vertex services first (commit b7f9fd3, PR #63), then Look Preview, Replicate and Amazon (commit b637695, PR #67).
The author used the breaker_machines gem pinned to 0.10.3, and says the DSL is clean and the wiring took an afternoon.
Follow any of these and your For You feed starts watching them — no settings page required.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
First-hand code, nothing checked twice
Quoted design comments, two commit SHAs, two PR numbers and a pinned gem version make this far more checkable than a typical personal blog post, and the counter diagnosis names a mechanism specific enough to be wrong in public: raw INCR writes a string, the default deserialisation path fails on it, nil.to_i is zero. All of it still comes from the one person who wrote the code. No one has opened those commits, corroborated the April 23 incident, or reproduced the nil read against breaker_machines 0.10.3.
One side project, six integrations
Deployment here means a single app: six integrations, one developer, two pushes in May 2026. The fix that made any of the breakers capable of tripping is a local prepend rather than an upstream release, so nothing suggests other breaker_machines users have it, and the rollout arrives without error-rate or incident figures on either side of it.
Title banks a second patch the text never spends
The prose under-sells more often than it over-sells: thresholds are justified by measured call volume, and the design note argues against the tidier shared-circuit option instead of claiming credit for it. Only the headline runs ahead of what is delivered, promising two gem patches where the copy we hold supplies one and then stops at the word "Finding".
Own blog, own app, no vendor in sight
The first line sends readers to meridianbuild.dev and the product the blog documents, so the piece doubles as a competence advertisement and traffic for OutfitMaker. Against that, no sponsor, client or employer appears, breaker_machines gets both praise and a bug report in the same post, and Vertex, Replicate and RapidAPI turn up only as things that can fail.
One account, and one detail already slipped
Treat this as one artifact read once. The claims are internally consistent and precise enough that a Rails developer could verify most of them in an afternoon, but none of them has been verified; and our own summary of where the text stops does not match the copy in front of us, which runs on through the first patch. Where the account of a source drifts, the parts nobody outside can inspect — the April 23 incident above all — stand on the author's word.
build
The 680 MB database that was really a 17 GB disk: self-hosted support platforms fail at month six1 publisher
build
Four indexes, none of them covering: the 78-second page and the one index that fixed it1 publisher
build
fal reports 35x MiniMax's own H3 endpoint after tuning the weights to its runtime1 publisher
build
A RAG stack lived seven hours before a hosted embedding endpoint returned 4041 publisher
Publishers with included, body-backed reporting in this cluster.
1 article · September 6, 2026