Thirty-two cards here, thirty-six rows in the ledger that ships beside this
page as sources.md, every one fetched on 11 September 2026 and every one from
the same two hosts. Filter by kind.
Postmortem
Shopify2019-07
semian #244: throttle half_open to closed attempts
An engineer quantifies how much worker capacity is consumed probing a dependency that
is still down, at the library's own default timeouts, and proposes tying ticket counts
to circuit state. Open since July 2019.
Carry forwardRecovery traffic is a capacity budget. Set the probe concurrency explicitly or inherit a 16.7% tax.
https://github.com/Shopify/semian/issues/244
Postmortem
Shopify2023-04
identity_cache #535: invalidations missed on schema rollout
The maintainer describes how schema-versioned cache keys create a one-directional
invalidation window during any rollout, how ordinary a trigger can be, and proposes
moving the schema hash into the value with a UUID data version.
Carry forwardVersion in the key equals partition at deploy time. Put the version in the value.
https://github.com/Shopify/identity_cache/issues/535
Postmortem
operator report2018-03
bootsnap #144: Rails boot failure when the cache dir is not writable
A read-only container image turns a boot accelerator into a boot blocker, with the
exact errno in the report. The requested behaviour, warn and continue, is the general
rule for every performance cache.
Carry forwardDeclare, and test, what your cache does when its store is unavailable.
https://github.com/rails/bootsnap/issues/144
Postmortem
Shopify2026-01
ruvy, archived: Ruby does not fit in Shopify Functions
The repository states that its Wasm modules exceed the maximum size Shopify Functions
accepts, lists ideas rather than a plan, and was archived read-only on 27 January 2026.
Carry forwardWrite the sandbox admission rule as a number first; then see which languages qualify.
https://github.com/Shopify/ruvy
Source
Shopifysince 2014-10
semian: circuit breaker and bulkhead in the worker process
Failure containment for a monolith, running since October 2014, with adapters for
MySQL2, Redis, Net::HTTP and both Active Record adapters. No sidecar, no extra hop.
Carry forwardWith many processes per host, host-local semaphores are a credible substitute for a mesh.
https://github.com/Shopify/semian
Source
Shopifysince 2014-10
toxiproxy: fault injection in every development environment
Built because existing tools "didn't provide the kind of dynamic API we needed for
integration and unit testing", and used in all development and test environments since
the same month Semian went in.
Carry forwardShip the failure-injection tool to laptops, not only to game days.
https://github.com/Shopify/toxiproxy
Source
Shopify2022-02
packwerk #169: caching the boundary check
An outside contributor takes the whole-monolith check from three and a half minutes to
under twenty seconds with a content-addressed cache, and documents the cache size next
to bootsnap's and Sorbet's.
Carry forwardStatic enforcement is a build-time cost; budget the cache before adopting it.
https://github.com/Shopify/packwerk/pull/169
Source
Shopify2024-05
packwerk #389, closed unmerged: no link to our own retrospective
A contributor proposes linking Shopify's Packwerk retrospective from the README. A
maintainer declines: "Those articles get old and change and might no reflect what the
tooling is anymore."
Carry forwardThe rejection record tells you what a project thinks it is. Read the closed pull requests before adopting a tool.
https://github.com/Shopify/packwerk/pull/389
Source
Shopify2022-10 to 2023-04
semian #420: the resiliency layer meets a new driver
Six months of work, closed unmerged, on classifying Trilogy's errors well enough for a
circuit breaker: the driver "seems eager about closing unused connections" and the
half-open timeout needed new client instances.
Carry forwardSwapping a driver means re-deriving your failure taxonomy. Cost that in, not just the wire protocol.
https://github.com/Shopify/semian/pull/420
Source
Shopifysince 2017-05
job-iteration: jobs built for tenant moves
Interruptible, resumable background jobs, used "to interrupt workloads safely when
moving tenants between shards and move shards between regions". The clearest public
statement of how the platform is partitioned.
Carry forwardIf tenants move, every long-running job is a migration hazard until it can checkpoint.
https://github.com/Shopify/job-iteration
Source
Shopifyread 2026-09
identity_cache README: the stated inconsistency budget
"IdentityCache is never going to be 100% consistent, since cache invalidations can be
lost", followed by the list of ways they are lost, from skipped callbacks to Memcached
restarts.
Carry forwardWrite your cache's failure modes into the README. Operators plan against stated budgets, not implied ones.
https://raw.githubusercontent.com/Shopify/identity_cache/main/README.md
Source
Shopifyread 2026-09
packwerk: boundaries without services
Packages, public constants, and an epigraph that frames the whole strategy: "This
knowledge is a dependency that raises the cost of change." The tool is still receiving
pull requests in 2026.
Carry forwardDependency cost and deployment cost are separable. Only pay the second when you need it.
https://github.com/Shopify/packwerk
ADR
Shopifyread 2026-09
packwerk USAGE.md: the todo file as a ratchet
package_todo.yml records existing violations to be "worked off over time";
enforce_dependencies: strict stops new ones being recorded at all. Two
settings, two eras of a codebase.
Carry forwardRetrofit a checker with a recorded baseline, then ratchet. A blocking checker on day one is a disabled checker on day two.
https://raw.githubusercontent.com/Shopify/packwerk/main/USAGE.md
ADR
Ruby / Shopifyread 2026-09
doc/jit/yjit.md: a JIT built inside the interpreter
"A lightweight, minimalistic Ruby JIT built inside CRuby" using basic block versioning,
written in Rust, with production stories solicited to a Shopify address and an MPLR 2023
paper cited for the evaluation.
Carry forwardImproving a runtime in place beats replacing it when the improvement can be upstreamed rather than forked.
https://raw.githubusercontent.com/ruby/ruby/master/doc/jit/yjit.md
ADR
Ruby / Shopifyread 2026-09
doc/jit/zjit.md: the second bet, method-based and profile-guided
"A method-based just-in-time (JIT) compiler for Ruby" that "uses profile information
from the interpreter to guide optimization", described as an advanced prototype.
Carry forwardA substrate investment is a standing commitment. The second compiler is a new multi-year project, not a version bump.
https://raw.githubusercontent.com/ruby/ruby/master/doc/jit/zjit.md
Source
RubyRuby 3.2
Ruby 3.2 NEWS: "YJIT is no longer experimental"
Promotion justified by production exposure: "tested on production workloads for over a
year and proven to be quite stable", with a 64 MiB default code budget and a call
threshold of 30.
Carry forwardIf you fund a substrate, you are also volunteering to be its first production workload.
https://raw.githubusercontent.com/ruby/ruby/ruby_3_2/NEWS.md
Source
RubyRuby 4.0
Ruby 4.0 NEWS: ZJIT ships experimental and slower
"As of Ruby 4.0.0, ZJIT is faster than the interpreter, but not yet as fast as YJIT",
with production readiness targeted for 4.1 and Rust 1.85 required to build it.
Carry forwardPlan substrate work in multi-year increments, and expect the replacement to be behind the incumbent for years.
https://raw.githubusercontent.com/ruby/ruby/ruby_4_0/NEWS.md
Source
Shopifyread 2026-09
Shopify/yjit: the repository that made itself redundant
"YJIT has been merged upstream, and is now an official part of Ruby 3.1+", with bug
reports redirected to Shopify's fork of CRuby. The strategy in one banner.
Carry forwardThe success condition for substrate work is that your repository stops being where the work happens.
https://github.com/Shopify/yjit
Source
Shopifyread 2026-09
yjit-metrics: benchmarking the bet in public
Continuous benchmarking and statistics for the JIT, published at speed.ruby-lang.org.
A public scoreboard is how an upstream investment stays accountable to the company
paying for it.
Carry forwardFund the benchmark harness at the same time as the optimisation, not afterwards.
https://github.com/Shopify/yjit-metrics
ADR
Rails / Shopify2023-04
rails #47880: upstreaming the Trilogy adapter
Shopify "adopted Trilogy successfully in our Rails monolith several weeks ago" and then
proposed the adapter to Rails, deliberately copying code verbatim first and cleaning up
later. Merged eleven days after opening.
Carry forwardAdopt, prove in production, then upstream. A private adapter is a tax you pay every framework release.
https://github.com/rails/rails/pull/47880
Source
GitHubread 2026-09
trilogy: the driver with a second operator
"Designed for performance, flexibility, and ease of embedding. It's currently in
production use on github.com", with no dependencies beyond POSIX, libc and OpenSSL.
Carry forwardPrefer a component that a second organisation already runs in production. One operator is a dependency; two is a standard.
https://github.com/trilogy-libraries/trilogy
Case study
Rails / Shopifyread 2026-09
bootsnap: the largest published figure, in someone else's organisation
"The core Shopify platform boots about 75% faster, dropping from around 25s to 6.5s",
alongside Discourse's independent 50%. The gem now lives under rails/.
Carry forwardDonate infrastructure once it stops differentiating you; the maintenance is worth more than the logo.
https://github.com/rails/bootsnap
Source
Bytecode Allianceread 2026-09
javy: the size rule that governs the extension platform
Modules of "1 to 16 KB range with use of dynamic linking" against "at least 869 KB"
statically linked. The same toolchain, two orders of magnitude apart.
Carry forwardOn a per-request sandbox, shared-engine dynamic linking is a precondition rather than an optimisation.
https://github.com/bytecodealliance/javy
Source
Shopifyread 2026-09
krane: a verdict layer over kubectl
Built because kubectl "leaves its users with some burning questions: What just
happened? Did it work?" Renamed from kubernetes-deploy at 1.0, and still tracking current
Kubernetes releases.
Carry forwardWhere you are a tenant of a platform, add the missing verdict rather than the missing platform.
https://github.com/Shopify/krane
Source
Shopifyread 2026-09
shipit-engine: one deploy tool across many stacks
"Used Shipit to synchronize and deploy hundreds of projects across dozens of teams,
using Python, Rails, RubyGems, Java, and Go", and it works with anything deployable by a
script.
Carry forwardA script-shaped deploy interface outlives the platforms underneath it. Couple to the verb, not the runtime.
https://github.com/Shopify/shipit-engine
Source
Shopifyread 2026-09
hydrogen: defined by its relationship to a router it does not own
"Hydrogen is designed to dovetail with React Router", and "Hydrogen legacy v1 has been
moved to a separate repo". Two sentences that describe a whole storefront strategy.
Carry forwardWhen your framework's identity is an adjective attached to someone else's, expect to move when they do.
https://github.com/Shopify/hydrogen
Source
Shopify2025-03
hydrogen-v1: the legacy that kept shipping
Behind a legacy banner, yet still cutting releases on branch
v1.x-2022-07 as late as 19 March 2025, years after the successor.
Carry forwardDeprecation is a multi-year support obligation. Budget the old version's releases, not just the new version's launch.
https://github.com/Shopify/hydrogen-v1/commits/main
ADR
Remix / Shopify2022-07-29
react-router 0005: Remixing React Router
The decision, accepted 29 July 2022, to move Remix's loaders, actions and fetchers down
into React Router, with router logic extracted into a zero-dependency package and hooks
renamed along the way.
Carry forwardWhen a framework pushes its ideas into its dependency, its users inherit the dependency's release cycle.
https://github.com/remix-run/react-router/blob/main/decisions/0005-remixing-react-router.md
ADR
Remix / Shopify2024-09-18
react-router 0011: routes.ts, and an adapter for the people left behind
Acknowledges that "when Remix changed its routing conventions between v1 and v2, some
users experienced friction", and ships a dedicated adapter package to carry Remix route
config into React Router v7.
Carry forwardAn adapter package in a decision record is a priced migration. Count them to measure a dependency's churn rate.
https://github.com/remix-run/react-router/blob/main/decisions/0011-routes-ts.md
Source
community2024-12-14
remix #10333: the migration tax, in users' words
"So you're asking Remix adopters to migrate Remix to React Router to Remix at some
future date?", and from another commenter, "started three remix projects over the past
12 months and the setup was totally different every time".
Carry forwardRead a dependency's discussion tab before adopting it. Churn shows up there a year before it reaches your backlog.
https://github.com/remix-run/remix/discussions/10333
Source
Remix / Shopifyread 2026-09
remix: the third foundation, away from React
"Welcome to Remix 3! The fully-stacked web framework", under active development, with
stated principles including "Model-First Development (optimizing for LLMs)" and
"Minimizing dependencies".
Carry forwardA framework that keeps changing its own foundation is telling you its roadmap. Believe it.
https://github.com/remix-run/remix
Source
Shopifyread 2026-09
Shopify/ruby: the company keeps a checkout of its own language
A fork of ruby/ruby carrying more than 100,000 commits, used as the intake for JIT bug
reports. Owning the constraint starts with being able to build it.
Carry forwardThe cheapest test of leverage over a dependency: can your team build and patch it today, from a checkout you maintain?
https://github.com/Shopify/ruby