StripeFable TalesProblem & solution
Formatting an entire 25 million line codebase overnight: the rubyfmt story
Summary
Stripe’s 25-million-line Ruby codebase needed a true autoformatter; before rubyfmt, no industry-wide Ruby formatter existed, and earlier tools had crashed on its files. rubyfmt began as a zero-configuration open-source project motivated by formatting disputes, Ruby’s slow startup, and the uncertainty faced by engineers arriving from other languages. To meet a 100ms target, it initially used a hand-authored C launcher and later moved formatting into Rust, with ripper parse trees first passing through JSON and eventually being deserialized directly from Ruby VALUE objects. Stripe adopted per-file opt-in, expanded coverage cautiously, and formatted the codebase on a Saturday in 2024; the excerpt reports that all 42-million-line Ruby codebase is now formatted. In 2025, migrating from ripper to Prism removed the need to link a Ruby VM and made rubyfmt smaller and dramatically faster.
Context
Ruby lacked a true autoformatter, while existing approaches could crash on Stripe’s files. Configurable linting also left room for style disagreements, and Ruby’s startup and Bundler overhead made format-on-save workflows too slow. Stripe additionally needed to manage merge-conflict and correctness risks when applying formatting across a very large codebase.
Approach / What changed
rubyfmt pursued zero configuration and a strict 100ms formatting budget. It used a hand-authored C launcher, later rewrote the formatter in Rust, optimized ripper parse-tree handling from JSON serialization to direct Ruby VALUE deserialization, and introduced per-file opt-in before broad rollout. The project later migrated from ripper to Prism, which can build parse trees without linking a Ruby VM.
Takeaways
rubyfmt targeted formatting latency below 100ms for all but the very largest files, avoiding normal Ruby and Bundler startup paths.
Stripe reduced rollout risk with per-file opt-in, gradual expansion, ripper-tree diffs, and a Saturday-wide formatting change intended to avoid merge conflicts.
Prism’s native parse trees removed rubyfmt’s serde and object-deserialization layers, shrinking the binary by megabytes and making it dramatically faster.
Source and freshness
- Source
- stripe.dev
- Published
- Added to Yomu
- Last updated
Summaries are generated from the original by a language model. Check the original before relying on it.
Keep reading
Related reading
The Good Stuff
Paid picks we use ourselves. Links carry a referral code — a subscription through one earns us a commission at no extra cost to you.
The best engineering reads, once a week
One useful email. Unsubscribe anytime.