Evidence ledger 26 sources Checked 03 Oct 2026

Evidence ledger

One row per claim in Scaling without splitting: a decade of Shopify, read from the code it published: who published it, what grade it carries, when it was written, when the link was last checked, and the quote or figure it rests on. Nothing in the guide is cited from memory, so anything not in this table is not in the guide.

Topic: how Shopify kept one Rails application as the unit of deployment between 2014 and 2026, and what it changed underneath the application instead: boundary enforcement as static analysis, resilience inside the database drivers, a live shard-moving engine for MySQL, and compiler work in the Ruby VM itself.

All links checked 2026-10-03.

Network note. This session's egress allowlist reached github.com, raw.githubusercontent.com, cloud.google.com and pkg.go.dev only. Shopify's engineering blog (shopify.engineering), its developer documentation, its Black Friday / Cyber Monday scale pages, conference-video hosts, bugs.ruby-lang.org (where the ZJIT feature ticket

21221 lives) and ACM's digital library (the MPLR 2023 YJIT paper) were all unreachable.

Everything below is therefore a repository artefact: committed documentation, pull requests, commits and one conference deck that happens to be committed into a repository. Where a claim would have needed a blog post or a paper, the guide says so rather than citing from memory. Issue threads are also absent: this session could search and read pull requests through the GitHub API but had no access to issues, so rejected issues are a gap while rejected and closed pull requests are not.

# Org Title Tier Published Checked URL Claim I take from it Supporting quote or figure
1 Shopify packwerk README source repo at 2026-08-25 2026-10-03 https://github.com/Shopify/packwerk/blob/main/README.md Boundaries in the monolith are enforced by a static analyser over autoloaded constants, not by a network hop "Packwerk is a Ruby gem used to enforce boundaries and modularize Rails applications"; "Method calls and objects passed around the application are completely ignored. Packwerk only cares about static constant references"
2 Shopify packwerk USAGE.md adr repo at 2026-08-25 2026-10-03 https://github.com/Shopify/packwerk/blob/main/USAGE.md The stated problem is a language gap, and the tool's answer to existing violations is a recorded backlog "Large applications need clear boundaries to avoid turning into a ball of mud. However, Ruby does not provide a good solution to enforcing boundaries between code"; "bin/packwerk update-todo should only be run to record existing violations and to remove violations that have been worked off. Running bin/packwerk update-todo to resolve a violation should be the very last resort"
3 Shopify packwerk, first commit source 2020-09-23 2026-10-03 https://github.com/Shopify/packwerk/commit/14890862e61869091813775d00d811213b09977a The tool is an extraction from the monolith, not a greenfield design Commit subject: "Extraction of Packwerk from the Shopify codebase"
4 Shopify PR #247, Pull privacy concerns out of packwerk source opened 2022-10-31, merged 2022-11-14 2026-10-03 https://github.com/Shopify/packwerk/pull/247 Of the two boundary rules shipped in 2020, only dependency direction stayed in the core tool; constant visibility was moved out to a separate gem "This PR removes privacy concerns out of the packwerk repository. It moves them to packwerk-privacy"; "Users will need to include packwerk-privacy in their Gemfile"; "This PR will require a major version bump"
5 Shopify packwerk v3.0.0 release tag source 2023-03-01 2026-10-03 https://github.com/Shopify/packwerk/releases/tag/v3.0.0 The privacy removal shipped to users in the 3.0.0 major version, four months after the merge Tag v3.0.0, commit dated 2023-03-01 in the repository history
6 Shopify Semian README source repo at 2026-09-07 2026-10-03 https://github.com/Shopify/semian/blob/main/README.md Resilience is implemented by monkey-patching the drivers in-process, with server-wide bulkheads in SysV semaphores, and has run in production since October 2014 "Semian is an extraction from Shopify where it's been running successfully in production since October, 2014"; "Controlling the concurrent access to a single resource, access is coordinated server-wide with SysV semaphores"; "Resource drivers are monkey-patched to be aware of Semian"
7 Shopify Semian README, bulkhead sizing source repo at 2026-09-07 2026-10-03 https://github.com/Shopify/semian/blob/main/README.md The ticket count is derived from an occupancy probability, with an explicitly accepted false-positive rate "there's a 10% chance they're talking to mysql_shard_0 at any given point in time under normal traffic. The probability that five workers are talking to it at the same time is 0.001%. If we only allow five workers to talk to a resource at any given point in time, and accept the 0.001% false positive rate"
8 Shopify Semian README, the cost of a 10s timeout source repo at 2026-09-07 2026-10-03 https://github.com/Shopify/semian/blob/main/README.md A circuit breaker alone cannot protect a thread-per-request server from a slow dependency "it will still take at least 10s before the circuit is open. In that time every worker is blocked ... this means we're at reduced capacity for at least 20s"; "It is paramount that you understand Semian before including it in production as you may otherwise be surprised by its behaviour"
9 Shopify Toxiproxy README source repo at 2026-08-25 2026-10-03 https://github.com/Shopify/toxiproxy/blob/main/README.md Failure injection is a test-environment dependency, in use since the same month as Semian "We've been successfully using it in all development and test environments at Shopify since October, 2014"; "Toxiproxy is the tool you need to prove with tests that your application doesn't have single points of failure"
10 Shopify Ghostferry README source repo at 2026-09-24 2026-10-03 https://github.com/Shopify/ghostferry/blob/main/README.md Moving a subset of rows between MySQL instances was built as a library, and specified in TLA+ with a caveat "Ghostferry is a library that enables you to selectively copy data from one mysql instance to another with minimal amount of downtime"; "the specification might not be entirely correct as proofs remain elusive"
11 Shopify Ghostferry technical overview adr repo at 2026-09-24 2026-10-03 https://github.com/Shopify/ghostferry/blob/main/docs/technicaloverview.md The cutover is a coordinated stop of writes outside the tool, and the tool's preconditions are hard constraints "Ghostferry mandates that you stop writes to the dataset you are copying at a stage of execution called cutover"; "Ghostferry can only be used on tables with auto incrementing, numeric, and unique primary keys"; "Ghostferry can only be used on a source database with FULL RBR"; "Ghostferry does not support tables with foreign key constraints"
12 Shopify Ghostferry verifiers adr repo at 2026-09-24 2026-10-03 https://github.com/Shopify/ghostferry/blob/main/docs/verifiers.md The verifier matrix states, per inconsistency class, which verifier catches it, including the cases none does "Data inconsistency due to missing binlog events when Ghostferry is resumed from the wrong binlog coordinates ... Sometimes"; "If the implementation of the Ghostferry algorithm is so broken, chances are the InlineVerifier won't catch it either as it relies on the same algorithm"; "NOTE! This is a deprecated verifier. Use the InlineVerifier instead"; "the CHECKSUM TABLE statement is broken in MySQL 5.7 for tables with JSON columns"
13 Shopify Ghostferry at Percona Live 2018, slides with presenter notes talk 2018-04-24 2026-10-03 https://github.com/Shopify/ghostferry/blob/main/docs/_static/percona-talk.pdf The tool exists because managed MySQL hides the filesystem and the replication interface, and TLA+ found a real corruption bug before release "Shopify is currently moving some databases to cloud based setups and we've managed to run into all of the issues we've discussed"; "we found and fixed an order of executing bug that can cause rare data corruptions"; "Warning: Finite model != proof of correctness"; "In most cases, this should be on the order of seconds. If you add in the verification ... it can be a matter of minutes"; "we are copying with 4x parallelism"
14 Shopify Ghostferry TLA+ specification source repo at 2026-09-24 2026-10-03 https://github.com/Shopify/ghostferry/blob/main/tlaplus/ghostferry.tla The formal model is committed beside the implementation, not written up and discarded File tlaplus/ghostferry.tla present in the repository tree
15 Shopify PR #307, Update go mysql to address a very rare data corruption problem postmortem 2021-09-21 2026-10-03 https://github.com/Shopify/ghostferry/pull/307 A string comparison of binlog filenames can silently end the binlog stream early, and no verifier catches it "Rare data loss due to binlog position comparison bug when binlog file numbering reaches 1M+"; "mysql.Position.Compare method was performing a string comparison of the binlog filenames, and thus incorrectly thinks that binlog file 999999 is larger than 1000000"; "This should be a very very rare condition, but a serious one as no online verifiers will be able to catch this kind of data loss"
16 Shopify PR #147, Fix possible data corruption due to UPDATE/DELETE not applied on tables with JSON columns postmortem 2020-01-17 2026-10-03 https://github.com/Shopify/ghostferry/pull/147 A type whose equality semantics differ from string equality turns every binlog UPDATE and DELETE into a silent no-op "when the JSON column is compared with a string in MySQL, it won't produce a match with anything. Thus UPDATEs and DELETEs fails"; "if the InlineVerifier is used on a table that has a JSON column and a composite PK where the pagination key is not the left most column in the composite PK, data corruption could occur WITHOUT the InlineVerifier notifying"
17 Shopify PR #287, Corruption when using FallbackColumn in sharding postmortem 2021-06-07 2026-10-03 https://github.com/Shopify/ghostferry/pull/287 An optimisation to the shard filter changed result-column order and broke an unstated assumption; the inline verifier stopped the run "since USING(FallbackColumn) will put FallbackColumn first in the result set, it will confuse Ghostferry and lose track of which value needs to go where"; "The inline verifier caught this and crashed Ghostferry correctly"
18 Shopify PR #176, Add Target verification against data corruption source 2020-04-21 2026-10-03 https://github.com/Shopify/ghostferry/pull/176 Writes arriving at the target from anywhere other than the migrator are treated as corruption, and the shard-moving team is named "An additional BinlogStreamer is attached to the target and registers a DMLEvent callback that extracts the annotations to verify they originated from Ghostferry"; review request "/cc @Shopify/pods"
19 Shopify Ghostferry sharding filter source repo at 2026-09-24 2026-10-03 https://github.com/Shopify/ghostferry/blob/main/sharding/filter.go The library ships a shard-aware copy filter, which is the unit of movement for a tenant ShardedCopyFilter with a ShardingKey and a sub-select pagination strategy
20 Ruby core / Shopify doc/jit/yjit.md source ruby master at 2026-10-03 2026-10-03 https://github.com/ruby/ruby/blob/master/doc/jit/yjit.md Shopify's performance answer was a JIT compiler inside CRuby, written in Rust, maintained from a company fork "YJIT is a lightweight, minimalistic Ruby JIT built inside CRuby. It lazily compiles code using a Basic Block Versioning (BBV) architecture"; "If you're using YJIT in production, please share your success stories with us! (ruby@shopify.com)"; "we suggest opening an issue or a discussion on the Shopify/ruby repository"
21 Ruby core / Shopify doc/jit/zjit.md source ruby master at 2026-10-03 2026-10-03 https://github.com/ruby/ruby/blob/master/doc/jit/zjit.md The second JIT is a different architecture: method-based and profile-guided, not basic-block versioning "ZJIT is a method-based just-in-time (JIT) compiler for Ruby. It uses profile information from the interpreter to guide optimization in the compiler"; bug reports go to "the official Ruby bug tracker (or, if you don't want to make an account, on Shopify/ruby)"
22 Ruby core / Shopify PR #13131, ZJIT source 2025-04-18 2026-10-03 https://github.com/ruby/ruby/pull/13131 ZJIT was developed in a private company repository and upstreamed while still unable to run most benchmarks "This PR upstreams ZJIT to CRuby"; "ZJIT is not yet ready for evaluation; it doesn't implement side exits or invalidations, so most benchmarks crash"; "For now, YJIT and ZJIT cannot be enabled together"; "Some commit messages refer to PRs in Shopify/zjit ... The repository is currently private"
23 Shopify (in rails/rails) PR #47023, Improve Rails' Shape friendliness source 2023-01-16 2026-10-03 https://github.com/rails/rails/pull/47023 Production data from the monolith is used to drive changes in the framework rather than in application code "This PR is data driven. I dump the list of Shapes from Shopify's monolith production environment, and Rails is very present among the top offenders"; top entry "770 @default_graphql_name"
24 Shopify (in ruby/ruby) PR #18433, Process.warmup: recompute allocatable_bytes postmortem 2026-08-22 2026-10-03 https://github.com/ruby/ruby/pull/18433 A monolith's boot allocations distort the VM's heap sizing in production, and the workaround is manual tuning that decays "A problem I ran into in production, is that the boot sequence, which tend to be allocation heavy, would cause the allocatable_bytes ... to grow much higher than what the application runtime actually needs"; "This resulted in GC not triggering for a long time, with the adverse effect of a unreasonably high memory usage and infrequent but long GC pauses"; "It works OK but is high maintaince as it needs to be retuned frequently"; measured 372.1MiB before, 57.1MiB after
25 Shopify krane README source repo at 2026-09-29 2026-10-03 https://github.com/Shopify/krane/blob/main/README.md Deployment tooling wraps kubectl to produce a verdict rather than replacing it "krane uses it under the hood! However, it leaves its users with some burning questions: What just happened? Did it work?"; "In a CI/CD environment, we need a clear, actionable pass/fail result for each deploy"
26 Shopify krane, rename commit source 2019-10-28 2026-10-03 https://github.com/Shopify/krane/commit/50e7217d98cb98dc4f96fc4e64ecfc5809daa085 The deployment tool predates the rename by nearly three years and is still being changed in 2026 Commit "Rename kubernetes-deploy to krane (#585)"; repository first commit 2017-01-17 "Init the gem", latest commit 2026-09-29
27 Shopify krane PR #431 source 2019-02-27 2026-10-03 https://github.com/Shopify/krane/pull/431 Secret material handled by the deploy tool leaked into its own output until a specific fix Title: "Removes the risk of sending decrypted EJSON secrets to output"
28 IBM (formerly Shopify) sarama CHANGELOG, v1.40.0 source 2023-07-17 2026-10-03 https://github.com/IBM/sarama/blob/main/CHANGELOG.md A widely used Go Kafka client Shopify maintained was handed to another company "Version 1.40.0 (2023-07-17) ... Note: this is the first release after the transition of Sarama ownership from Shopify to IBM"; breaking change "chore: migrate module to github.com/IBM/sarama"
29 Go module index pkg.go.dev entry for IBM/sarama vendor 2026-10-03 2026-10-03 https://pkg.go.dev/github.com/IBM/sarama The ownership change is visible in the module path every dependent had to edit Module page served at github.com/IBM/sarama
30 Shopify / Bytecode Alliance javy README header commit source 2023-05-16 2026-10-03 https://github.com/Shopify/javy/commit/3dbe247e9ba84e9715ce3daa3c36af9e07a912d9 The JavaScript-to-WebAssembly toolchain Shopify started in 2021 became a Bytecode Alliance project Commit "Update README to use Bytecode Alliance header (#366)"; repository first commit 2021-04-23
31 Bytecode Alliance javy README source repo at 2026-10-02 2026-10-03 https://github.com/bytecodealliance/javy/blob/main/README.md Sandboxed extension code has a size budget that drives its linking model "Javy can create very small Wasm modules in the 1 to 16 KB range with use of dynamic linking. The default static linking produces modules that are at least 869 KB in size"
32 Shopify identity_cache README source repo at 2026 2026-10-03 https://github.com/Shopify/identity_cache/blob/main/README.md Read scaling was bought with an opt-in cache inside the ORM, invalidated on commit "Opt in read through ActiveRecord caching used in production and extracted from Shopify"; "uses an after_commit hook to expire those objects, and any up the tree, when they are changed"
33 Shopify maintenance_tasks README source repo at 2026 2026-10-03 https://github.com/Shopify/maintenance_tasks/blob/main/README.md Backfills over a large dataset became a first-class, pausable, resumable product surface "By 'maintenance task', this project means a data migration, i.e. code that changes data in the database, often to support schema migrations"; "They can be paused or interrupted"
34 Shopify go-lua README source repo at 2025-07-18 2026-10-03 https://github.com/Shopify/go-lua/blob/master/README.md The company has been embedding sandboxed interpreters since 2013, starting with load generation "go-lua is a port of the Lua 5.2 VM to pure Go"; "it is used to describe flows in Shopify's load generation tool, Genghis"; first commit 2013-12-20
35 Ruby core (formerly Shopify) ruby-bench source 2026-10-03 2026-10-03 https://github.com/ruby/ruby-bench The benchmark suite built to justify YJIT now belongs to Ruby; Shopify/yjit-bench redirects to it README: "Clone this repository: git clone https://github.com/ruby/ruby-bench"; "ruby-bench supports benchmarking any Ruby implementation"
36 Google Cloud (vendor) Shopify case study vendor 2026 (undated on page) 2026-10-03 https://cloud.google.com/customers/shopify Where the platform runs now, in the vendor's words, and the newest layer added on top of it "Shopify also uses solutions such as Bigtable, BigQuery, Compute Engine, and Google Kubernetes Engine"; "when upgrading from Claude Sonnet 4.0 to 4.5, the new model was deployed into production in less than 24 hours"
37 Shopify Shopify/ruby fork source 2026-10-03 2026-10-03 https://github.com/Shopify/ruby The company keeps a public fork of the language it runs on, used as an issue tracker for its compiler work Repository exists and is referenced from both JIT documents in ruby/ruby as the place to file bugs and discuss patches

What the ledger does not contain, and why that matters

  • No incident review. Shopify publishes none that this session could reach. Rows 15, 16, 17 and 24 are graded postmortem because they are engineer-written accounts of production- affecting defects with mechanism, detection and fix, which is the closest the public record comes. A reader should treat the absence as a real gap: there is no published account of what happened to Shopify's availability when any of these mechanisms failed at scale.
  • No cost figures. Nothing in the repository record prices a shard move, a cluster, or the engineering time spent on two JIT compilers.
  • No traffic or fleet numbers. The Black Friday figures Shopify publishes annually were on unreachable hosts; the guide uses none of them rather than quoting them from memory.
  • No issues, only pull requests. Rejected designs that were argued out in issue threads are invisible here.