00:00:10
I feel like I'm supposed to start with something upbeat — “Woo! Yeah, we're here in Amsterdam. It's amazing.” — but I'm not going to do that. I'll start with a little rant instead because I'm continually amazed by a curious paradox in our industry. In many ways, this is the best time ever to be a software developer: there is more free open source than ever, computers are faster, and everything should be wonderful. So why does it sometimes not feel that way? Why do we fail to recognize the progress we're supposed to be enjoying, and why do many days feel like we're moving backward?
00:00:56
One reason is that we've forgotten to ask what the actual problem is that we're solving. We've sliced big problems into tiny little slices, worked on those isolated pieces, and though each slice may improve, when you add them up the whole can actually get worse. That's a curious phenomenon I've dedicated my career — and my work on Rails — to addressing: not thinking of problems as isolated slices but thinking about the whole problem of web development, and today even more than that.
00:01:50
I've been around long enough to remember when we've gone backwards. When I started in 1999, I edited a web application with PHP and HTML in one CVS repository, and somehow we shipped great software used by lots of people on 1999-era hardware. Today it often feels like everything needs everything all of the time and everyone involved just to ship anything at all. What happened? How did we go from big dog to little dog?
00:02:36
The deployment story is even stranger. A single developer in 1999 could deploy a change in literally five seconds — I know because that's how I did it: drag the file in my FTP manager and it was live. Today, we're told a strong team could deploy in 15 minutes, but in practice people are deploying in 30 minutes, an hour, three hours, even eight days. Something has gone seriously wrong when we've regressed from FTP in five seconds to modern workflows that take an hour or more.
00:03:33
The number of moving parts needed to create web applications today has exploded. To what end? Are we building magically better applications than in 1999 using space-age technology? No — we're doing the same CRUD work: reading and writing from databases and formatting HTML. We now use CSS, which is progress, but in all this complication we have made systems more brittle. We used to commonly have three nines of uptime; today, people struggle to match that even with Kubernetes, AWS, Datadog and more. We're not necessarily making things better. The common explanation is that merchants of complexity con us into adopting complicated tools. I wrote a blog post about this: yes, merchants of complexity exist and they sell complicated products that make the world worse. But they only succeed because people buy from them. They profit because we have a psychological need to appear as more than CRUD monkeys.
00:05:04
Embrace the monkey. CRUD is what a lot of our jobs fundamentally are: reading from a database, creating records, updating and deleting them. It's simple at its core, and using the web for that job is a great way to make a living. But it can feel too simple, not computer-sciency enough, and that drives a desire for unnecessary complexity. I think that's one of the root causes. If we happily and proudly embrace CRUD, we're free to solve problems end to end. That doesn't mean stripping everything to the bone; Rails has always been a mega-framework intended to provide most of what people need to build web applications: templates, database access, routing, email, background jobs, and more. This isn't minimalism — in many ways it's maximalism: solving the annoying problems common to web development.
00:06:29
That philosophy has fallen out of favor among authors of many new frameworks today; few aim to address the whole problem. In the open-source world we should return to solving full problems as Rails has done from the start. I like to think of this as the Roman Empire — not its fall, but its height: Pax Reelsana — where provinces work well together not because of technology alone but because of a shared philosophy. That philosophy has motivated me to expand this peaceful empire of tools and ideas further.
00:08:07
In the grandest terms: libertas, proprietas, pas — freedom, ownership, and duty. You have the freedom to do whatever you want with Rails — it's just Ruby code, you can bundle open it and change it, even monkey-patch if you like. That degree of ownership is wonderful. We pride ourselves on using sharp tools and being owners of our code. We're not mere consumers waiting for gifts from some magic vendor; we're contributors. You're supposed to do your part for the framework and for open source. I'll start by doing my part: what we've been doing at 37signals over the past year to bring gifts to the community. We will proceed in two ways: expand the borders of the empire — conquer new territories and problems — and also prune areas where we've overcomplicated things.
00:11:00
Let's start with 'more.' One concrete more is Markdown. Markdown is wonderful and has become the lingua franca for AI — AI loves Markdown and, curiously, emojis. We want to make it easier to use Markdown in Rails, both as input and output, and make Markdown a common expectation. I've been writing manuals in Markdown — the Writebook — and we should make it easy to download a manual as a single Markdown file. In Rails 8.1 you'll be able to use format.md and render markdown; you can pass any object and we'll duck-type it to call to_markdown. There's a PR pending for Writebook and I hope to ship it during the conference so you can download manuals as Markdown.
00:12:12
We also have a new text editor for Action Text called Lexi. Trix, our current editor, covered the basics adequately, but it didn't receive enough community maintenance. We've decided to make Lexi the new default editor in Action Text. Lexi provides a live view with syntax highlighting for Ruby and many languages, which is great when inserting code into Basecamp or other apps that use Action Text. Following the Markdown work, you can paste Markdown into Lexi and it will convert it to rich text, and you can also extract Markdown from it.
00:13:40
What is Lexi? It's a use of Lexical, a text editing framework made by Meta that powers WhatsApp, Instagram and Facebook, serving billions of users daily. Meta is motivated to maintain Lexical, so we get an upgrade and someone else does the heavy lifting — a form of performance optimization. Last year I introduced House, a Markdown editor we've been using in Writebook. We tried House in two new products — Fizzy and another unreleased product — and found many users don't want raw Markdown. Markdown is great for developers and AI, but not for everyone. So we've moved to Lexical for those products and will stop investing further in House.
00:16:32
Another addition coming in Rails 8.1 is Active Job Continuations: a new way to structure jobs so they can be interrupted and resumed without losing progress. This became important at 37signals when we moved out of the cloud to Kamal: when we deploy a new version we shut down containers running the old code within 30 seconds, which is incompatible with long-running jobs like exporting huge accounts. Making jobs resumable means we don't throw away work and can cut jobs into resumable steps.
00:17:32
Those ideas are within the known borders of our empire, but we border the native app world, which can be a bit hostile. We can't seal off that frontier; native apps matter for competitive web experiences. We learned this when we launched Hey and Apple tried to block us. Whether we like it or not, if you have a business that needs customers, customers want native apps. We've been building hybrid applications with Hotwire Native and integrated tooling. A key question is offline support: what happens when you need email on a plane without internet? Offline support should be solved at the layer of the framework, so we're building Turbo Offline to cache content on the device and allow offline access. Step one (shipping soon) is a cache-as-you-go: when you open an email it will be cached and available offline. Step two will let us preemptively cache pages like your travel folder.
00:20:01
Turbo integrates into Hotwire Native, which manages native concerns. I won't dive into Hotwire Native now — there's an expert session later — but another native frontier is finally solving push notifications. What I called Action Notifier last year morphed into Action Push. Today we have Action Push Native to send native notifications directly to Apple and Google, which was necessary when we shut down our AWS account and stopped using Pinpoint. Action Push Native wraps that functionality, letting you register devices and tokens, attach platform-specific metadata, and send silent notifications when needed. Configuration will be done in a new config/push.yml with keys for Apple and Google.
00:24:02
The other part is web push. I was excited about web push when we launched Campfire, which is a native-like web app that uses web push. Web push works reasonably well but not perfectly; native notifications remain advantageous in deliverability and control. If you're using Campfire during this conference and getting push on your phone, that's coming via Action Web Push. The Campfire implementation is more cumbersome and still needs extraction into a standalone project — I intended to do it but I'm busy — so instead I'm offering Campfire for free on the condition that someone extracts the Action Web Push code. Look for the URL after the keynote and help extract it.
00:24:37
That's a lot of 'more' we're adding into the framework: some shipping in Rails 8.1, some in the next release. But a healthy empire also needs pruning: retracting where we have dead branches or dumb code. Sometimes things are outdated because we were simply wrong; other times underlying technology has moved forward. For example, for local development I replaced Puma Dev with the simplicity of localhost: you don't need Puma Dev or local SSL if you use localhost because since 2017 localhost is a secure context. That realization simplified our local development URLs: explicit ports correspond to processes on your machine, so running multiple apps on different ports makes sense and removes complexity.
00:26:00
We also rethought Docker in development. Docker is great for running services like databases in specific versions, but running all development inside Docker is painful. Instead, run native Ruby — now managed well by tools like rbenv or asdf or mi — and use Docker only for versioned DB services. We share a set of Docker databases by version so each app can connect to the DB version it needs. That isolates the main pain point while keeping native development fast and simple. One of the bigger pain points we tackled was system tests. Ten years ago I declared system tests the future; in theory they're wonderful because they test everything end to end, but in practice they're brittle, slow, and fragile. Last year we removed most of our system tests in Hey, keeping only a small set of smoke tests. I've never heard of a bug we pushed to production that those system tests would have caught. So in Rails 8.1 we're removing the recommendation to generate system tests for every new controller; the framework still supports them, but they should not be the default.
00:28:48
As we left the cloud, one thing that irritated me was the slow cloud test runners. A small app's test suite ran in ten minutes on carefully configured cloud runners. That felt unacceptable. But local hardware improved dramatically thanks to modern Apple silicon and other advances. For example, the Hey test suite — tens of thousands of assertions — can run locally in far less time on modern machines: on an M4 it's under four minutes; on a fast AMD box it's about 1 minute 12 seconds. For most Rails apps, you can run your entire test suite locally quickly if you pin dependencies appropriately. Running tests locally removes the need for slow cloud runners.
00:31:10
The key objection is 'it works on my machine' — but if you pin your database and Ruby versions (we use versioned Docker DBs and mi for Ruby), then local runs are reproducible. We've run this setup for a long time without issues, and the payoff is huge: knowing whether your PR is ready in one minute and twelve seconds is liberating. We don't remove CI protection: we use GitHub features requiring human sign-off that they ran the local tests and verified they passed. Trust largely works in organizations: developers want to ship working software and lying on an attestation is a career risk. In Rails 8.1 we've baked in a way to run all of this locally: a new DSL to declare your local CI runs (linting, audits, tests) and to require human sign-off before merging. Running locally takes very little time.
00:34:26
All the benchmarking of local test speeds made me realize we were paying cloud providers to run slow tests while our machines could run them fast. It reminded me that real-time systems, like Fortnite rendering at 120 Hz with 8 ms budgets, can't tolerate minutes-long waits. We're waiting way too long on many things — deployment is a prime example. We'll apply engineering discipline and set budgets. First, a bootstrap budget: a new developer should not spend hours setting up a laptop. At 37signals our goal is that in 15 minutes a cold machine with nothing on it can be fully set up and able to deploy a change to production.
00:36:44
To achieve that, we built our own OS image and setup tools. Inspired by people like Ellen Kish, we made our own operating system build — Omachi — and we're going to install it live on stage to show how fast this can be. The plan: boot from a USB key and install Omachi on a brand new Framework desktop within our budget. I switched to Linux about eighteen months ago and started with Ubuntu, but then I discovered Linux 'ricing' and tiling window managers like Hyperland and was pulled down the rabbit hole. Modern Linux is very good: many long-standing issues have been fixed over decades of development. After obsessive tinkering, Omachi is a tailored experience for web developers built on a modern Linux foundation.
00:44:03
Things got good: the live install finished in under five minutes. That demonstrates what obsessed open-source communities can produce. After installing Omachi, we can make a Rails app in minutes because Omachi ships with everything a developer needs: git, mi, docker, databases, and more. I demonstrated creating a new Rails app, generating a scaffold, migrating the database, and running the dev server — hello Rails — all very quickly. In about six and a half minutes we booted the new OS and had a Rails app running.
00:46:24
Omachi is intended to be the best way to develop Ruby on Rails and we hope you'll try it. We have 200 USB keys with Omachi at the 37signals booth for people serious about installing it. Omachi ships with useful defaults: aliases like R for rails, a Starship prompt, and tools such as lazygit inside neovim for fast Git workflows. We can preconfigure your user, email, and aliases so commits work out of the box. Because it's our OS, we can include everything a developer needs without begging Apple for permission.
00:49:11
After creating Omachi I realized our entire developer onboarding at 37signals should be this fast. We built a tailoring script that installs everything and checks out the necessary repos in a few minutes so the developer is ready. With our bootstrap budget we want to be able to deploy from a fresh machine in three minutes. That's achievable: I showed a deploy of Fizzy in 58 seconds on stage; Basecamp 4 takes about four minutes today and we'll shave it to three.
00:50:00
I've also become interested in powerful but inexpensive mini servers. I run Campfire on a modest box in a closet with 76 cores and ~300 GB RAM — it barely breaks a sweat and cost around $300. That same performance in the cloud would cost hundreds or thousands per month. This got me thinking: if such performance is available for hundreds of dollars, what could enterprises do with micro data centers? At 37signals we run a couple of data centers and now an outpost in Amsterdam, but what if instead of huge data centers we had many small outposts closer to users?
00:51:15
Latency matters. Light around the earth is a theoretical limit: one round trip around the globe is about 137 ms, and actual network RTTs are higher because cables don't follow a straight line. New York to LA RTT is ~70 ms; New York to Sydney is ~220 ms. Those latencies add up: a POST, a redirect, then a GET can consume many hundreds of milliseconds simply due to distance. In contrast, local requests in Copenhagen can be 2 ms, across a country 8 ms, or 25 ms within Europe — huge improvements. If most customers are within 25 ms of an outpost, user experience feels much faster. This motivates edge computing and many small outposts.
00:55:03
To make many small outposts feasible, we had to rearchitect some fundamentals. We built Active Record tenancy so each customer has their own database, letting us place the database near the customer. This improves performance, isolation, backups, and privacy. For syncing many databases we built Beamer, a simple way to replicate SQLite databases at scale. SQLite is uniquely suited to one-database-per-customer approaches: we replicate tens of thousands of databases and sustain tens of thousands of transactions per second by optimizing for this scale. Finally, we extended Kamal proxy with a geo component so requests can be routed to an outpost near the user. Readers are safe to access anywhere, but writes must be routed to the dominant writer. We rely on HTTP semantics (per RFC 2616) to restrict writes to POSTs and use session affinity with transaction IDs so a client is redirected to a reader only when that reader has applied the write. If not yet ready, the reader can return a header that instructs the client where to go.
01:01:33
So our gift exchange includes many things: Active Job Continuations in Rails 8.1, Action Push Native (in beta), Turbo Offline coming soon, Hotwire Native 1.3, Action Text Lexi (beta today), Active Record tenancy, Beamer, Kamal Geo Proxy, and local-development improvements: running native Ruby with Docker DBs, using localhost, rethinking system tests, and running local CI. Some of these are shipping in Rails 8.1 now. I invite you to check out Omachi, rethink what Linux can be, and join us in doing more end-to-end problem solving and owning every part of the stack. We should be able to change anything we want — own everything end to end — and not accept restrictions from vendors like Apple.
01:03:04
I want libertas, proprietas, pas — freedom, ownership, and duty. What you do with those virtues is up to you. Thank you so much.