Ruby & Rails - a Chat with Maintainers
See all speakers
See all 4 speakers


Ruby & Rails - a Chat with Maintainers
Aaron Patterson, Hiroshi Shibata, Jean Boussier, and Robby Russell • Amsterdam, Netherlands • Talk

Date: September 05, 2025
Published: Mon, 15 Sep 2025 00:00:00 +0000
Announced: Tue, 20 May 2025 00:00:00 +0000

Join maintainers of Ruby and Rails for an insightful conversation about the current state and future direction of both projects. This panel discussion will cover recent developments, upcoming features, and the collaborative efforts between the Ruby and Rails core teams.

Rails World 2025

00:00:09 Good morning, everybody. Hello — how's everyone doing? Wonderful.
00:00:20 All right. Here's the first question for each of you: what's something you've recently helped with in either Ruby or Rails that you're proud of and that might surprise people? We'll start with you, Aaron. Wait — what was the question again?
00:00:45 I don't want to spoil it because I have a keynote at the end of the day, so if you want to hear more, please come to my talk later. But I can say I've been working on ractor-related stuff and improvements around parallelism; I'll go into more detail in my presentation.
00:01:23 I added an automated release workflow to Ruby core using GitHub Actions. Previously releases could take six to nine months of preparation plus many hours on release day. Now we can tag and push on GitHub, and the workflow builds packages, creates Docker images, and updates the official sites. That lets us ship stable versions every two or three months and reduces release-day work to about an hour, so people can get newer Ruby versions much faster.
00:02:34 I recently optimized ActiveSupport's JSON handling. After improving the JSON gem's performance, someone pointed out ActiveSupport still wrapped a lot of extra work that made things slow in apps. ActiveSupport used to walk the entire object tree looking for as_json methods, duplicating work done by the JSON generator. I refactored it to only call back when encountering an unknown object, which dramatically reduces unnecessary processing. We also examined HTML-entity escaping in JSON and realized it's only needed when embedding JSON in HTML, so we made that path much more efficient. These changes should land in Rails 8.1.
00:04:20 What has gotten better for Ruby developers in the past few years? Pretty much everything — precompiled gems are a big win, LSP support for editors is maturing, and garbage collection has improved significantly. These things have made development smoother overall.
00:04:57 If you're not familiar, an LSP is a language-server protocol: a common interface that editors use to implement language features in a single, shared way. Microsoft standardized it and it's just a JSON-based protocol, but it has made a huge difference for editor tooling.
00:06:01 Maintaining CI and infrastructure has improved too, but there's still a lot that's harder than it should be. Complexity has grown: everything gets better yet also harder. Setting up a development environment is still a pain for newcomers — missing libraries, OpenSSL compilation errors, and the many steps before you can do meaningful work are common friction points.
00:06:54 As maintainers, many of us run edge or main branches ourselves so we see breakages early. That helps catch regressions but reduces the pressure to cut releases. It's a trade-off: using edge gives confidence in stability for users of the cutting edge, but it can delay releases. We probably need some calendar reminders to ship more regularly. In short: being a maintainer often means running the latest code and balancing stability with progress.
00:10:36 When I review issues or PRs for projects like rake, I follow a straightforward workflow: triage reports, fix bugs, open pull requests, tag releases, and push. We rely heavily on GitHub and GitHub Actions for cross-platform testing. For Ruby core, the CI is massive: a push starts over a hundred jobs on GitHub Actions, and we also run a secondary, internal CI that tests many platforms and architectures you wouldn't normally see on GitHub.
00:13:14 Running a full CI suite is often much more than what a laptop can do, so CI can be a productivity multiplier: you push and let the servers run while you work on the next thing. On performance work, I often do it because it's fun; meaningful performance improvements require profiling your whole application, not just microbenchmarks. The optimizations that matter are those that reduce time across the entire architecture and are validated by real-world benchmarks. Microbenchmarks can be useful for spotting bottlenecks, but they don't always translate to real benefit in production.
00:17:36 There's room for debate: many small improvements add up, but opportunity cost matters. We only have so much time. Another big improvement in Ruby has been regular-expression handling: the regex engine has been improved to avoid many pathological slow cases, and Ruby 3.2 introduced a global timeout for regexes so long-running regex matches can raise instead of hanging a process. That eliminated a whole class of security vulnerabilities.
00:21:06 I've worked on changes like frozen string literal behavior. Ideally we wouldn't need per-file magic comments; I have a migration plan to make frozen string literals the default, but it's a hard decision because flipping defaults is breaking and we must weigh costs versus benefits. Once a language or framework API is published, accidental behaviors tend to be relied on by users, so changing them can be painful.
00:23:14 Maintainers do develop thicker skin — or at least the appearance of it — because breaking changes generate strong reactions. Some cope by reading less email; others ask users to try edge versions and report issues. If you maintain widely used tools, you often run those tools daily, find problems, fix them, and release regularly to keep things stable for everyone.
00:25:02 There are legacy choices we sometimes wish we could redo. For example, decisions around extracting small utilities like a base64 implementation into separate gems can create friction: users must add a dependency even for trivial functionality. That can lead maintainers to remove dependencies and ask whether extracting the library was the right call in the first place.
00:26:24 Some big Rails changes felt risky to ship — like optimizing Active Record internals and rewriting the router — but in the end they worked well because they were carefully tested. I also made a risky optimization in Ruby itself for the triple-dot argument forwarding that eliminated many allocations. It required confidence because of C-level inline caches and parameter passing semantics; to be sure it was safe we ran it against large real-world codebases and added missing test cases upstream in CRuby. Those large test runs are what give maintainers the confidence to push risky but valuable changes.
00:31:24 Please test your applications against edge Ruby and edge Rails. If you can set up a nightly CI that runs your test suite against weekly builds of edge, it helps everyone catch compatibility issues earlier and reduces painful breakage after a public release.
00:31:58 In tooling, I removed a default content-type header from the next version of net/http; that might break some applications, so please try the preview if you use net/http. Another notable change was around YAML safety: YAML.load used to deserialize arbitrary objects, which created security issues. We added YAML.safe_load to prevent unsafe deserialization, but many libraries called the unsafe load API. Rather than keep adding safe APIs that people forget to use, we made a decision in a major release to make load behave like safe_load by default. That broke some code, but it eliminated an entire class of vulnerabilities and was the right long-term choice.
00:36:19 Security changes are painful because they cause busy work for many maintainers, but they prevent recurring vulnerabilities. Another example: Rack deprecated the symbol unprocessable_entity in favor of unprocessable_content to match the HTTP spec; Rails chose to retain the old symbol as an alias and backported it to save developers hours of work. These decisions often come down to empathy and weighing the cost of breaking existing apps versus the benefit of aligning with specs or reducing risk.
00:38:34 Windows support is important for expanding the Ruby and Rails user base. Historically Ruby's Win32 support has been limited and many Ruby installations relied on MinGW, which isn't native Windows tooling. Improving official Windows packages and supporting Windows developers — including those who use it as a primary development environment — helps onboard more people. WSL (Windows Subsystem for Linux) has made running Linux toolchains on Windows easier and is a practical recommendation for many users, but native Windows support still matters.
00:43:24 One persistent pain point is installing Ruby and gems with C extensions. Different user environments, compiler versions, and platform quirks (for example GCC 15 breaking older builds) cause many installation errors. Ideally we'd have a robust precompiled gem distribution so maintainers of small C-extension gems wouldn't need to manage per-platform builds themselves. If someone could provide an easy system to publish precompiled gems for all platforms, it would solve a lot of friction for users and contributors.
00:47:16 After someone types rails new, the biggest surprises for beginners often come during dependency installation: bundle install and native extensions are where things commonly break. Rails itself provides many options and features that new users may not need; an interactive rails new that asks a few questions or offers a curated default path could help newcomers discover the right setup without being overwhelmed.
00:50:02 (Light moment) Two years ago I was asked my favorite color and I said, 'Blue, I guess.' That led to a long-running joke. Hiroshi announced his favorite color as purple. The debate continues; for the record, I'm still guessing.
00:51:06 If Rails were started from scratch, some features might not be included as defaults. For example, serialized columns that implicitly rely on YAML can cause long-term pain because YAML serialization ties to internal representation and can break across upgrades. Rails historically used marshalling in caches and serialized columns; that makes internal representation difficult to change safely. When frameworks accidentally expose implementation details that users rely on, it limits our ability to improve performance or change internals. It's important to design with long-term compatibility in mind and to avoid implicitly serializing internal state that people may persist for decades.
Explore all talks recorded at Rails World 2025
+19