Maintaining the Local Workshop: Robby Russell on Why Mending Is the Job
Ruby on RailsRobby Russell, founder of the Rails consultancy Planet Argon, gave the closing keynote at Rails World 2026. The central question: when producing code is getting cheaper, where does the most valuable engineering work actually happen? Russell's answer is that much of it lies in tending the environment a team works inside. That environment is a "local workshop" of patterns, workarounds and unwritten rules built on top of Rails. It matters more now that AI coding agents have to rediscover all of it every time their context resets.
Russell framed the talk as reporting rather than prediction. The observations come from Planet Argon's client work, from roughly eight years of podcast interviews, and from conference hallway conversations. Russell described their role as that of a "field correspondent": the talk offers "field notes" about what is already happening, not forecasts of where software engineering will be in five months or five years.
Four Ways to Build the Same Integration
The talk opened with a consulting engagement. A company with a mature Rails application had roughly doubled its engineering team, to about 40 or 50 engineers, in a little over a year. Over the years it had built hundreds of integrations while onboarding customers. Each integration did roughly the same thing: receive data, transform and validate it, send some of it elsewhere, handle errors, retry, log what happened, and notify someone when things went wrong.
Yet the codebase contained four different patterns for doing this. One came from an idea an engineer had read on another company's engineering blog years earlier. Another came from a different team's blog. A later hire experimented and added a third approach, and experiments kept accumulating. Each approach technically worked and made sense when it was introduced. The problem, Russell said, was that none of the earlier approaches ever went away.
Russell asked the audience to imagine being an engineer who had joined six months earlier. When you hit one of the older integrations, do you follow the pattern you think the team uses now, or bring the old code in line with it? If you start cleaning up, how far do you go? Sometimes you just need to make a quick change and get out, and that, Russell noted, is exactly how old patterns survive. Nobody commits a change saying they have decided to make the platform confusing for every future hire. It happens gradually, one decision on top of another.
The company asked Planet Argon to review the code, interview the engineers, and help choose which approach to standardize on. On the surface this looked like a routine architecture engagement. The team asked the engineers to explain the patterns, describe the friction, identify which constraints still applied, and say what they would reach for if they had to build a new integration tomorrow. According to Russell, it quickly became clear that architecture was not the real problem. The problem was that nobody was willing to be the person who said, "We're doing it this way now."
Russell said they understood why. Most of the people working in the codebase had inherited the patterns rather than created them, and many had joined after the original engineers left. For some it was their first large Rails application. The company saw that as a strength of Rails: engineers with little Rails experience could become productive quickly. But those engineers arrived to find four competing approaches running in production, all apparently working. Who were they to decide which no longer fit?
How Oral Traditions Form
Russell pointed to a second reason this happens. Engineers are rarely hired with instructions to reconsider the development environment. They are hired to ship features, fix bugs and shorten the backlog, so they pick up the next ticket. While doing that work, they run into things. Russell offered a list, some of it deliberately exaggerated:
- three different service object patterns in the codebase
- saving one Active Record model triggers five callbacks, spawns two background jobs, broadcasts something, and sends a message to what seems to be a fax machine in an office known only through rumor
- deploys take 18 to 32 minutes "depending on the day of the week and where the sun is"
- changing one field in one form requires five changes across two repositories
None of these stop you from closing the ticket. They just make the work harder to navigate. So you assume the people who have been there longer must know a reason. If you ask, you hear something like, "Yeah, that's a little weird. I wouldn't worry about it too much today." Six months later a new hire asks you, and you give the same answer.
Eventually, Russell said, a team builds an oral tradition around avoiding things nobody understands anymore, and that tradition makes every old decision look intentional. A mature app contains deliberate choices, expired constraints, experiments that stuck around, and workarounds nobody has revisited. The difficulty is that "they're all written in the same font."
Over time people do get good at navigating all this. They learn where not to step, which tests need rerunning, which examples are safe to copy, and whom to ask before touching billing code. They learn that the README is "more of a historical document than a reliable set of instructions," and they learn the difference between what the application says and how the team actually works on it. The danger, Russell argued, is that the better we get at compensating for something, the less unusual it feels.
Makers and Menders
More than a decade ago, Russell came across a post by Andrea Goulet of Corgibytes describing "makers" and "menders." Paraphrasing: makers are drawn to creating something new that didn't exist before, while menders are drawn to tending, repairing, improving and extending what already exists. Russell identifies as a mender: give them something that mostly works, occasionally catches fire, and carries a 2013 comment reading "temporary workaround, remove after launch," and they're curious.
The distinction stuck with Russell because, despite how the industry talks about itself, most professional software work is not done on a blank canvas. Few engineers spend their days designing new architecture and shipping new features. Most are tending decisions already made: changing software without breaking what people depend on, updating dependencies, chasing regressions, reducing risk, and trying to remember why someone thought adding GraphQL would improve everything.
Engineers tell themselves that once a few maintenance issues are cleaned up, they will return to the "real" work: the innovative, fun, feature work. Russell called this a lie and repeated it for emphasis: "The lie is that tending to the system takes us away from the job." For most people, tending is a substantial part of the job. Sometimes the higher-leverage work is improving the conditions around the work, making the system easier to understand and changes safer to make, evaluate and trust. That, too, is mending. Often the original engineers are gone, and the current team has to work out what was intentional and what is simply "accumulated sediment."
Russell summarized the field notes this way: producing code has gotten easier and cheaper, but understanding what belongs, what can be trusted, and what should change still requires judgment, "at least for now."
Rails as a Shared Workshop
Russell argued that this theme fits Rails World in particular because Rails has spent more than 20 years improving what Russell calls "the workshop." It has done so not perfectly, not always consistently, and perhaps with a bit too much confidence. The community has invested in the environment around web application development: shared conventions, predictable structure, sensible defaults, reusable abstractions, documentation, open-source collaboration, arguments, online examples, prior art, and the steady removal of unnecessary decisions.
Rails did not eliminate complexity, Russell said, but it provided a common place to begin. In an unfamiliar Rails app you already have some idea where to trace a request, where database changes live, where background jobs typically run, and where tests are. That reduces the number of questions humans have to answer before they can start evolving an app. The answers aren't always perfect, but a shared answer is far more valuable than relitigating every decision.
On top of that shared base, every application builds a "local workshop" with its own patterns, shortcuts, tools, exceptions and assumptions. Those local choices become the environment the team works inside.
Rails also provides comparison. After working across several Rails applications, you start to recognize what is conventional, what is a reasonable local adaptation, and what is unusual. That comparison is how judgment and expertise develop, and it is also, Russell joked, what keeps them in business. But someone in their first mature Rails app lacks that comparative experience, so everything in the repository looks equally authoritative simply because it is there. Shared conventions give a baseline for asking better questions. Is this how Rails would normally approach it? If not, was the departure intentional? Did a constraint push the team another way, and does that constraint still exist? Or is this an experiment that never reached a conclusion?
Russell asked the audience to think of a folder, pattern, library or piece of infrastructure they know how to work around but aren't sure why it exists in its current form. If the honest answer to a colleague's question is "Yeah, that's a little weird," Russell said, "that's what it sounds like when context has disappeared."
Agents Read the Repository as Evidence
AI agents entering a Rails app benefit from the same conventions, Russell said. They already have a reasonable idea where to look and what patterns to expect, so they have fewer possibilities to consider before getting to work. The shared workshop is already teaching them.
But a Rails app can bury that leverage under years of conflicting local patterns, dead code, outdated instructions, unnecessary dependencies, and decisions nobody feels authorized to revisit. The framework can't prevent a team from building four competing answers to the same question, can't make them choose one later, can't decide when a local constraint has expired, and can't make people share what they've learned. That part, Russell said, still belongs to the team, "for now."
Agents also read the repository as evidence. A human newcomer eventually learns that one directory is current and another is being abandoned. Russell acknowledged that you can tell agents similar things today, but said an agent may simply see three plausible examples and have to relearn the distinction each time its context window is cleared. The ambiguity was always there; agents expose how much humans had learned to work around.
Russell's example was prompting an agent to "make CI faster." It might find an expensive step, improve caching or split jobs, and after a few cycles you might save a minute. That's useful. But you can't leave it running forever and expect CI to keep getting faster. Eventually it hits questions that aren't really about code: how much do we trust what it produces, can we test it, can we understand failures, can we trust the feedback, and how much risk will we tolerate? Russell said teams are still wrestling with these because they are questions about how teams want to operate.
Tidy First and a New Mythical Man-Month
Russell turned to Kent Beck's 2023 book Tidy First?. Its core idea: before making a difficult change, first make the change easier. If a ticket's requested behavior is straightforward but the surrounding code isn't, tidy that area first and keep the tidying separate from the behavior change. Simplified, one ticket might become two pull requests, each easier to approve than one large PR.
That rule, Russell argued, assumed tidying was expensive, because the person doing it paid in their own time. Hand the same rule to an agent, and one ticket can become several PRs: behavior changes, documentation, more tests, maybe dependency bumps. That looks productive until you are the one reviewing it all. Russell quoted Beck from the previous December saying that "the Genie produces code at a pace that no human reviewer can match," and stressed that review is only part of it. Someone still has to understand what changed, test it, coordinate it with everything else, and decide what belongs in the system.
Russell connected this to Fred Brooks, who wrote more than 50 years ago about why adding engineers doesn't give a matching increase in capacity: more output creates more coordination. Russell wondered aloud whether the industry has entered its own version of The Mythical Man-Month. The cause isn't hiring 20 more engineers overnight; it's suddenly being able to produce more work than teams can keep up with. All that output still has to land somewhere.
Russell noted one upside, jokingly: agents don't need feedback conversations. You can tell them their abstraction is bad or their PR too large, or simply clear the context, switch models and start over, with no need to schedule a one-on-one.
The Hotel Shower Problem
To illustrate how people compensate for bad environments, Russell asked how many audience members had spent an unreasonable amount of time that week figuring out their hotel shower, possibly standing there partially undressed, thinking they must be smarter than this. Many hands went up. Everyone knows how showers work, yet there they were turning knobs and pulling things to learn the local conventions. Tomorrow they'll be faster, and from the hotel's perspective the shower works fine.
Software teams do this constantly, Russell said. They know the app's seed task doesn't really work, so they have their own way of getting usable data locally. They know a certain error message means something completely unrelated. The software didn't improve; people learned to compensate. Russell showed a list of such frictions and promised to share the slides.
Humans are remarkably good at this. They remember exceptions, skip broken instructions, know which command not to run, and learn who holds undocumented context, until the workarounds feel normal. Agents, Russell said, don't necessarily build that same durable understanding. They search again, infer again, and burn tokens getting back to what the humans already know. The agent makes the cost of the workshop's friction far more visible.
Who Improves the Workshop Without a Platform Team?
Some organizations have platform engineering teams, or similarly named groups, focused on the environment around writing and operating software: developer setup, CI, deployment, internal tooling, safer production access, shared workflows. Their job is to make the environment easier to work in over time.
Russell cited two conversations. Austin Story at Doximity described an internal skills marketplace, so that useful workflows don't stay trapped in one engineer's local setup or prompt history. Brian Scanland at Finn, interviewed on Russell's podcast On Rails, described shared skills anyone across the organization can use, including non-engineers, plus wrappers around tools like Rails console and Rails runner that give agents more controlled ways into the production application. Different companies, similar patterns.
But most people in the room, Russell acknowledged, won't return to work to find five new hires dedicated to internal developer experience. On a team of 20, eight or three developers, who notices recurring friction and deals with it? The work doesn't disappear just because nobody owns it.
Be Q, Not Bond
Russell's answer drew on James Bond. Q runs MI6's research and development branch and builds the tools and gadgets, such as the pen that "will clearly become important 45 minutes later in the story." Bond gets the mission, the chase, the martini, and drives the expensive car into the ocean. Q improves the environment the mission takes place in.
Engineering culture, Russell said, encourages people to imagine themselves as Bond. But sometimes the most valuable person on the team is the one ensuring "that the next mission requires less heroism": building a safer tool, shortening feedback loops, removing a path nobody should take anymore, making it easier for the next engineer or agent to succeed. The gadget is only an artifact; the value is in what the next person or agent can do with it.
You Don't Need Permission to Do Your Job Well
When Russell talks with engineers about this kind of work, the same hesitation comes up: I was hired to build features and close tickets. You hit some friction, suspect there's a better way, but nobody asked you to fix it, so you keep working through the backlog. How do you decide whether it's worth the time? Are you breaking a commitment, overspending on a small problem, or learning something that will help someone else?
Russell was explicit that this isn't a call for reckless action. Going rogue for three months to build an internal developer portal nobody asked for "is not stewardship. That's a hostage situation." But spending a little time understanding recurring friction seems reasonable, and Russell said: "You do not need permission to do your job well." If you, your coworkers, or your agents keep hitting friction, alleviating it is part of the job. It doesn't have to be a big project: name the friction, find someone else who feels it, improve one small thing, and see what you learn.
Russell also offered, half-jokingly, a "new card to play." If questioned, you can say the team's AI agents kept hitting a snag that sent them into a death spiral and burned tokens looking for a workaround. Agents burning money, Russell observed, now provides an argument teams were never allowed to make when the waste was human time. The practical question is what the smallest responsible improvement would be that is visible, reversible, and useful to someone else. You may not own the whole workshop, but there's probably at least one drawer nobody has reorganized since 2019.
From FAFO to WUTS: Wonder, Unpack, Tinker, Share
Russell warned against leaving the conference to hunt for things to fix. These things come up naturally, and when one catches your eye, it helps to give that curiosity structure so you don't fall down rabbit holes.
Russell contrasted this with the familiar "FAFO" method: sitting at your code wondering what it does and what would happen if you deleted it. Poking software is sometimes the fastest way to understand it, though maybe not in production. As a more deliberate alternative, Russell proposed WUTS (pronounced "what's"): Wonder, Unpack, Tinker, Share. It is loosely inspired by inquiry-based learning and scientific experimentation, and by Russell's need to give a silly name to otherwise normal behavior. Russell stressed that it isn't a problem-solving framework, since engineers are already problem solvers.
Wonder starts with a small moment of surprise. Code isn't doing what you expected. Two people describe the same workflow very differently. A rake task only worked the second time. Russell treats that curiosity as a signal, while distinguishing it from being personally irritated by a naming decision someone made 12 years ago, which isn't worth dwelling on. The examples Russell suggested looking for are ordinary rather than architectural: a setup step you always forget, a warning everyone ignores, a comment referring to a vendor nobody mentioned during onboarding, or a timeout set to exactly 47 seconds.
Unpack means separating what you assume from what you can learn. It starts with archaeology: how did this get here, what problem was being solved, what constraints existed then? Code that looks ridiculous today may have made perfect sense six years ago. The key is resisting the jump from "huh" to "I know how to fix this." Gather evidence first: follow the behavior far enough to explain it, look at production, measure, read the history, and find the change that introduced it. If you still need more, find someone who might remember.
Sometimes the original engineer has left. Russell ran what they called a very unscientific poll on X and LinkedIn asking developers whether they would be willing to be tracked down about a decision made five years earlier at a company they no longer work for. Of a little over 200 responses, about eight in ten said they'd be willing to help. Russell's suggestion was to take git blame a step further and look people up on LinkedIn, but only after doing your own homework. Sometimes that homework reveals the thing that caught your attention was less interesting than it seemed, a step Russell said people often skip.
Tinker means making the smallest reversible change that yields useful information. Information is the goal; tinkering doesn't need to produce the finished solution, and learning your assumption was wrong can be the useful outcome.
Share is the step Russell thinks many teams skip entirely. It doesn't mean posting on Slack that you learned something weird. It means turning what you learned into something the next person can use: documenting constraints and recording decisions, but also building a tool so nobody has to remember the workaround, or showing someone how something works. The point is to put the knowledge back into the environment. The opening company, Russell noted, had experimented a great deal but hadn't consistently closed that loop, so engineers inherited four equally plausible answers.
Two Worked Examples
In the first example, a new engineer looks at order.save. It seems ordinary, but it triggers callbacks that spawn jobs, broadcasts, auditing, cache invalidation, and updates to a warehouse inventory system nobody mentioned during onboarding. The engineer wonders what actually happens, then unpacks by tracing callbacks and mapping side effects. Having done that work, the engineer shouldn't leave the understanding in their head. It could become a Mermaid diagram in the repository, or at least a sketch in the wiki.
The second example, which Russell said came from a real case Planet Argon found, is middleware untouched since 2018 that scrubs Unicode from incoming requests. Its comment says to remove it once the legacy mobile app is retired, and you're fairly sure that app was sunset before you were hired. Unpacking the history reveals it was added after a miserable weekend with hundreds of production errors in Bugsnag, which is more interesting than the comment suggested. Rather than deleting it, you add instrumentation or logging and wait. A week later it has fired 41 more times, none from the retired mobile app: the traffic comes from a crawler and from one partner's webhooks.
The behavior may not change at all, but the comment does, so the next person knows why the middleware exists and what depends on it. That's a useful outcome, Russell said, because "not everything old is wrong." The goal isn't eliminating every oddity in a codebase but distinguishing "intentional weirdness from forgotten weirdness."
Seeing Your Own Workarounds
People often stop noticing their own workarounds because they've become part of how they work, Russell observed, but it's easier to spot someone else's. Russell recommended sitting or pairing with a colleague on ordinary tasks and resisting the urge to help or instruct. Just observe: where do they pause, what do they repeat, what do they avoid, what workarounds have they developed? They may not notice these themselves. Russell also suggested watching agents, since they haven't learned the team's workarounds yet. In a Q-themed aside, Russell mentioned a small item in attendees' swag bags for their return to work.
A Letter to Your Replacement
Another exercise Russell uses to locate undocumented context: imagine it's your last day on the application and you're never coming back. Write a letter to your replacement that begins, "Dear replacement, welcome to the party. This is mostly a normal Rails application, except..." What's weird? What would you warn them about? Which commands should they avoid? Which areas depend on context you know isn't written down anywhere?
For extra credit, ask a few coworkers to write their own letters and compare them. Do they warn about the same things? Does one engineer know about a constraint no one else mentions? What gets written down, Russell said, is essentially the team's oral tradition, and the gap between what the application says and what the team knows is also part of the workshop.
What the 2026 Rails Community Survey Suggests
Russell shared an early finding from the 2026 Rails Community Survey, whose full results were still forthcoming. Asked where people struggle most when joining an existing project, respondents ranked first understanding the domain model and business logic, second understanding old or inherited code, and third a lack of documentation. Russell didn't find this surprising but saw a theme: the struggle isn't figuring out how to write the next piece of code but understanding the system just inherited. That points to where to invest: places where shared understanding is weak and rediscovery is expensive.
Make the Path Obvious
Russell grouped improvements into three broad categories. The first is making the path obvious. If a team regularly adds integrations, one approach is telling people to copy the most recent one, which works until the most recent one turns out to be an experiment. Alternatively, encode what the team has learned into a generator that creates the expected class, configuration, error handling, fixtures, stubs, documentation, whatever belongs in every integration. The decision becomes executable: humans and agents can use it, and reviewers appreciate the consistency.
Russell distinguished three tools. A repository instruction says "this is how we work." A canonical example says "this is the one we currently mean." A generator says "start here." All reduce the number of plausible choices, but the generator gives you a starting point instead of asking you to interpret one. Russell called this "Rails-style leverage" applied to the local workshop. For agents, Russell said they would much rather hand over a generator reflecting current expectations than ask an agent to search the repository, find 242 plausible examples, and synthesize a 243rd. Russell allowed, though, that agents might work around this anyway.
Make Feedback Fast and Trustworthy
The second category is feedback: fast feedback that lies isn't helpful, and slow feedback everyone ignores isn't either. Every engineering environment has a hidden user manual that nobody wrote, reviewed or approved, but everyone learns. Stop running the full test suite locally because it takes too long. Staging is rarely reliable. Certain warnings are always ignored. The environment taught those rules.
Agents inherit the same hidden manual. They still wait on CI and still have to judge whether a failure means anything. Attaching a fast coding agent to a slow, unreliable feedback loop leaves it operating inside a slow, unreliable system. Russell suggested asking where everyone is waiting, what takes 40 minutes that could take five, which errors send people digging through old Slack threads, and what feedback arrives so late that people have already moved on. Not every check needs to be instant; some should take time or run closer to production. The goal is the right feedback at the right stage.
Here Russell offered a second image alongside Q: the guitar tech. Russell, a musician, said being a guitar tech might have been a dream job in another life. The tech tunes instruments for the next song, stays nearby to help when something starts going wrong, and after the show fixes whatever caused problems so nobody has to deal with them tomorrow. They seem to work for the musician, but really they work for the audience. For software teams, Russell said, that audience is the people using the software.
Make Mistakes Cheaper to Reverse
The third category is making mistakes cheaper to reverse. Russell deliberately did not say "prevent mistakes," calling that "a lovely ambition but a terrible operating model." If every experiment feels irreversible, people stop experimenting. That isn't laziness; they're managing risk.
Russell described the familiar pattern: one deployment, migration or forgotten config file, and three engineers spend days debugging production. The mistake wasn't the expensive part; recovery was. After a few such incidents, the team learns to be careful, not touch that, get more people in the room, and wait until Monday. That fear becomes part of the workshop. Feature flags, reversible migrations, preview environments and smaller deploys give teams somewhere safer to be wrong. They don't eliminate mistakes but make recovery cheaper, and when recovery is cheap people explore. When it's terrifying, they stop touching things.
Reduce Obsolete Choices
Across all three categories, Russell added one more practice: removing obsolete choices. Every abandoned pattern still in the codebase keeps teaching that "this is one way we do things around here." Engineers tend to assume leverage comes from adding something, but sometimes it comes from removing what nobody should use anymore. "Deletion is an architectural decision," Russell said. Improving the workshop can mean building a tool, labeling a drawer, or documenting why an odd tool still needs to be there. The goal is making the preferred way a bit more obvious to whoever, or whatever, comes next.
"We're Doing It This Way Now"
Returning to the opening company, Russell said it didn't really need outside experts to find the right architecture; there probably wasn't a perfect answer. There was a choice that fit the current system well enough to document, test, generate, review consistently and improve later. What they needed was someone willing to say, "We've learned enough from these experiments. We're doing it this way now." Not forever, just long enough to stop making the same decision independently every time.
Russell suggested the same thing is likely happening in the audience's own codebases. Teams work inside decisions made for different moments. Some still fit, some were temporary, some were left behind by a former coworker, and years later nothing indicates which is which, because they're "all still written in that same damn font."
Russell closed by asking people to pay attention when something makes them pause, follow that curiosity, and when they learn something useful, give the next person a place to start. That person might join in six months, or might be an agent arriving tomorrow morning with none of the team's accumulated workarounds. Not everyone needs to be Bond; sometimes the valuable work is putting a better tool in someone else's hands so the next mission needs less heroism. Russell's final claim was that the engineers who create the most leverage won't just be the ones producing more inside the workshop, but the ones improving it.
All right. So, I was having this conversation with this company that reached out to us. They had a mature Rails application with years of history behind it and a growing engineering team. I think they had roughly doubled to like 40, 50 engineers in a little over a year. And they found themselves in the situation where they had four different patterns, I guess you can say, of implementing roughly the same types of things in their application. You see, over the years, they had built hundreds and hundreds of integrations as they were onboarding new customers to their platform. And each of these integrations needed to do roughly the same sort of thing. Receive some data, transform it, validate it, send some of it somewhere else, handle errors, retry things, log what happened, and notify somebody when things go sideways. You know, software.
But every generation of these integrations looked very different. One approach came from something that one of the engineers read on someone else's engineering blog years before. And then another came from something that somebody read on another engineering team's blog. Does that sound familiar? And then somebody else came along and joined the team and they started experimenting and came up with another idea and they kept accumulating all these experiments on top of it. Now each of these approaches technically worked, but it was kind of part of the problem. They started with this initial approach. It solved that initial problem for the application at that point in time and that was for a while just simply how they did things. But then the team began to experiment,
and those experiments also made sense for that point in time as well. But the problem was that none of those earlier approaches ever really went away. They just kept accumulating. So now imagine you're an engineer working in this application today and you've only been there for 6 months. When you encounter one of these older integrations, do you follow the pattern that you think the team is now using when they've hundreds and hundreds of integrations, or do you try to bring it in line with what you think the team is doing today? And if you do start cleaning up, how far down that path do you go?
Sometimes you just kind of need to jump in on something, make a quick change, and get out, right? But that's also how old patterns survive. Rarely are we going to find a commit in our git history that says, "I've just decided to make this platform confusing for everybody that ever joins this company." No, these things happen gradually. One decision that keeps accumulating on top of another.
So they asked my team to come in, review their code, talk with their engineers, and help them decide which approach they should standardize on. On the surface, sure, this sounded like your kind of run-of-the-mill "we need some help with our architecture," needed a fresh set of eyes from experts, right? So we did that. We reviewed the code. We talked with their team and we asked them to explain the different patterns that they were using, what was causing friction, what constraints they thought still applied, and if they had to build a new integration tomorrow, what would they reach for?
Pretty quickly it became obvious that architecture wasn't really the problem here. The problem was that nobody was willing to be the person who said, "We're doing it this way now." And to be honest, I understood why. You see, most of the people working on this codebase hadn't created those original patterns. They had inherited them. Many joined after many of the original engineers had left. For some, this was their very first large Rails application. In fact, the company talked about how this was one of the strengths of Rails, that they could hire these talented engineers with very little Rails experience and get them up and running pretty productive. But those engineers arrived to find four competing approaches already running in production and they all seem to work. So who are they to kind of come in and decide which ones no longer fit?
And there's another reason this happens. Most engineers aren't hired with the explicit instructions of "please come in and reconsider the development environment that we've already created for you." You're hired because there's work to do, right? There's features to ship, bugs to fix, and a product backlog to shorten, or at least try to. So naturally, that's what you focus on. You pick up the next ticket and you try to get that work done.
But while you're trying to do that work, you encounter things. Maybe there are three different service object patterns floating around in the codebase. Maybe saving one Active Record model triggers five callbacks, spawns two background jobs, broadcasts something, and sends a message to what appears to be a fax machine running in an office you have only ever heard about. And if you rumors between your team. And maybe deploys take 18 to 32 minutes depending on the day of the week and where the sun is. Maybe changing one field in one form requires you to make five different codebase changes across two repositories.
Now, none of these things are necessarily stopping you from closing that ticket. They're just making the work a little harder to navigate. So you think, huh, the application seems to be working and there are other people here who've been here longer than me. So maybe nobody's on the team. So maybe there's a reason for this. Occasionally, you might even ask somebody, "Hey, what's up with this weird thing over here?" And they're like, "Yeah, that's a little weird. I wouldn't worry about it too much today." And that makes sense because you got that ticket to close, right? 6 months later, somebody else joins your team and they ask you about it and you find yourself saying, "Yeah, that's a little weird. I probably wouldn't worry too much about it."
Eventually, your team builds up an oral tradition around avoiding things that nobody really understands anymore, making every old decision look intentional.
But a mature app contains a lot of deliberate choices, expired constraints, experiments that stuck around, and works that nobody has revisited. But the difficult part is that they're all written in the same font.
The good news is that over time we do get pretty reasonably good at navigating all this. We learn where not to step, which tests need to be rerun, which examples are safe to copy. We learn who to ask before we touch any of the code related to billing, which parts of the app require just a little extra TLC. We learn that the README is more of a historical document than a reliable set of instructions. We learn the difference between what the application says and how that team actually works on it. And so, we compensate. But the dangerous part is that the better that we get at compensating for something, the less unusual it starts to feel. And this is part of what makes software such a different kind of engineering work, even if we're not going to be doing this much longer.
Now, a little over a decade ago, I came across this post by Andrea Goulet from a company called Corgibytes describing makers and menders. And I'm paraphrasing her here, but makers are drawn towards creating something new, inventing, innovating, making something that didn't exist before. Menders are drawn towards tending, repairing, improving, and extending what already exists. And that distinction resonated with me. Personally, I gravitate towards the mender label. Give me something that mostly works, occasionally catches fire, and has a comment from 2013 saying "temporary workaround, remove after launch." Now you have my curiosity.
The reason that that stuck with me is that despite how our industry talks about itself, most professional software work isn't performed on a blank canvas. Most of us are not waking up every morning, drinking our cup of coffee or tea, and then getting to design new architecture patterns and shipping new features all day. We're tending to decisions that have already been made. We're changing software while trying not to break the parts that people still depend on. We're updating dependencies. We're chasing regressions. We're reducing risk and trying to remember why somebody thought it was a great idea to add GraphQL to this and it was going to improve everything. Thank you, Bruce. So we spend years telling ourselves that once we just clean up a few main room issues, we'll finally return to the real work, the innovative work, the fun work, the feature work, right? And yet somehow the existing system keeps requiring our attention.
The lie is that tending to the system takes us away from the job. Let me repeat that. The lie is that tending to the system takes us away from the job. For most of us, it's a substantial part of the job. Sometimes the higher leverage work is improving the conditions around the work, making the system easier to understand, making changes safer to make, evaluate, and trust. That's mending, too.
And sometimes the original engineers are long gone and the current team is left trying to figure out what was intentional and what was just simply accumulated sediment.
Now I'm not standing up here today with a collection of war stories and consulting success stories where Planet Argon arrived, saved the day, and rode away into a cleanly refactored sunset. But these are patterns that I keep running into in our client work, from podcast interviews I've been doing over the last eight years, and from hallway tracks at conferences like this. I'm here today as kind of a field correspondent. These are not my predictions of where I think software engineering will be 5 years from now or 5 months from now. These are field notes about what's already happening. And here's what I'm seeing. Yes, producing code has gotten easier and cheaper, but understanding what belongs, what we can trust, and what we should change still requires judgment, at least for now.
Now, one reason that this feels especially relevant at Rails World is that Ruby on Rails has been improving what I like to refer to as the workshop for more than 20 years. Not perfectly, not always consistently, maybe even with just a little bit too much confidence. But the Rails community has spent those years investing in the environment around application development, primarily web application development: our shared conventions, predictable structures, sensible defaults, reusable abstractions, documentation, open source collaborations, arguments, online examples, and prior art, and the steady removal of unnecessary decisions.
Rails did not eliminate complexity in building web apps, but it gave us a common place to begin, because you can enter an unfamiliar Rails application and already have some idea of where to look. Where do you trace a request? Where do you find database changes? Where does background job work typically happen? Where do the tests live? That common structure has given us leverage as humans because it reduces the number of questions that we need to answer before we can begin evolving our own apps. Where do these types of files live? How do we represent these types of relationships? How do we validate this record? How do we render this type of response? Now, the answers aren't always perfect, but having a shared answer is far more valuable than having to relitigate every decision.
So, again, Rails gives us a starting point, but every one of our applications builds what I like to refer to as a local workshop on top of it. It has its own patterns, shortcuts, tools, exceptions, and assumptions. And those local choices eventually become the environment that the team has to work inside.
And Rails gives us something else that's useful here. Comparison. Once you've had an opportunity to work across several Rails applications, you start to recognize what's conventional, what's a reasonable local adaptation, and what's unusual about a codebase. That comparison is how we develop judgment and expertise in our careers, and keeps me in business. But someone entering into their first mature Rails app may not have any of that comparative experience yet. Everything in the repository looks equally authoritative simply because it's already there.
Shared conventions, yes, give us this baseline. They give us somewhere to scan where we can start asking better questions. Is this roughly how Rails would normally approach this? And if it isn't, was that departure intentional? Were some of these constraints pushing a team in a different direction? Maybe there was, but does that constraint still exist today? Or are we looking at an experiment that never really reached a conclusion?
So, take a moment and think about your apps for a second. Is there a folder, a pattern, or a library or some part of your infrastructure that you seem to know how to work around, but you're not entirely sure why it exists in its current form? Has someone ever asked you about it and you've responded, "Yeah, that's a little weird"? That's what it sounds like when context has disappeared.
So now we have these agents joining us as well and taking our jobs. But when these agents enter into our Rails apps, they already have a reasonable idea of where to look for things, how things are typically structured, and what patterns they're likely to encounter. They have fewer possibilities to consider before they can get to work. The workshop is already teaching them how we've been working on our apps. And over these 20 years, we've been working on making Rails apps much more legible, repeatable, and shared. And now we're going to have these AI agents working with us, and they're going to be benefiting from this.
But our Rails app can still bury that leverage beneath years and years of conflicting local patterns, dead code, outdated instructions, unnecessary dependencies, and decisions that nobody really feels authorized to revisit, because the framework can't prevent us from building four competing answers to the same question. It can't make us choose one of them later. It can't decide when a local constraint has expired and it can't make us share what we've learned with each other. That part still belongs to all of us, for now.
And again, now we have these agents joining us and they too are reading the repository as evidence. Human newcomers will eventually learn that one directory is current and another is being abandoned in a few months. Yes, we can kind of tell our agents to do similar things right now. Kind of a simple point here, but an agent will just see three plausible examples and may have to relearn that distinction every time its context window is cleared. That ambiguity has already been there, but the agents are exposing just how much we've learned to work around.
Have you ever prompted an AI agent with something like, "How can we make our CI faster?" I think we probably all tried this. Maybe you skipped the pleasantries and you said "make CI faster." Maybe it found an expensive step. Maybe it improved some caching in your CI. Maybe it split up your jobs. Maybe after a few prompt cycles, you saved a minute off of your CI build. Great. That's useful.
But you probably can't just leave the agent running forever and expect the CI to keep getting faster and faster until the tests finish before you've even written them. Eventually, it's going to run into questions that aren't really about code anymore. It's going to be: how much do we trust what it's producing? Can we test it? Can we understand what failed? Can we trust the feedback that we're getting? And how much risk are we willing to tolerate? These are still decisions that we're all wrestling with as teams, because these are the questions about how we want to operate ourselves.
Now, in 2023, Kent Beck published this book called Tidy First? Anybody read it? Great. And one of the core ideas is really simple. Before you make a difficult change, first make the change easier. You pick up your ticket in Linear or Jira. Now, the behavior that's being requested by whoever put the ticket in seems to be straightforward, but the code around it isn't. So, you have an opportunity to tidy that area first. That tidying work stays separate from the behavior change. So, the idea
basically is that one ticket might result, I'm simplifying, it might result in say two pull requests. Each one is supposedly easier to say yes to. So, you don't have one big PR, you have two smaller PRs. And now we got stacked PRs and things like that.
Now, that rule assumed that tidying was expensive because when you're the one having to do the work, that extra tidying work has real cost, your time. But now, we can hand that rule to an agent.
One ticket can now lead to maybe several PRs, behavior changes, documentation, better, more tests, maybe even dependency bumps, which sounds and maybe looks productive until you're the one having to review it all.
Kent Beck's been talking a lot about this since. And here he was last December saying, "The Genie produces code at a pace that no human reviewer can match. And reviewing the code is only part of it. Somebody still has to understand what changed, test it, review it, coordinate with everything else that's happening. Somebody still has to decide what belongs in our systems."
Now, this isn't entirely a new problem. It isn't. It isn't. But more than 50 years ago, Fred Brooks was writing about why adding more engineers doesn't just give you a matching increase in capacity. More output also creates more coordination, aka more people, more problems. I think that was basically the genesis of his book there.
So, I find myself wondering, have we already entered into our own version of The Mythical Man-Month? Not because we've suddenly hired 20 more engineers, but because we're suddenly able to outproduce the amount of work that we can keep up with. All that output still has to land somewhere.
There's an upside though. Agents presumably don't take feedback. You can tell them that their abstraction is bad, their PR is too large, and they need to restart over. Or you don't even have to tell them. You just clear, start over, switch your model. You don't need to schedule a 1:1, give them any feedback and be like, "Hey buddy, we need to talk about your PRs." But they are still entering into the same
show of hands. How many of you had to spend an unreasonable amount of time figuring out the shower in your hotel this week? Keep your hand up if at some point you're standing there maybe even partially naked. I'm imagining you all naked right now. It helps me get through this, but, and thinking surely I must be smarter than this, right? Excellent. Thank you for contributing to today's hotel shower research segment of my talk.
Presumably you know how showers work, right? I think most of you have probably been using them most of your life. And yet there you are turning knobs, pulling on things, trying to figure out the local conventions.
Eventually, you'll figure it out. And tomorrow morning, let's assume, or unless you take showers at night, you'll probably be faster. And from the hotel's perspective, the shower works. We have showers. It works great.
We do this in software all the time. We know that our app's db:seed task doesn't really work. So, we wouldn't use that. We have our own way of getting usable data into our local environments. We know that that error message means something completely unrelated. The software didn't improve either. We just learned how to compensate for it.
And that workshop contains a lot of friction we've learned to overlook. This is just a small sampling of things off the top of my head. And don't worry, I'll share the slides this week. So, you know, I'll take a photo for evidence, but I suspect a few of these are all too familiar.
Humans are remarkably good at compensating for this ship. We remember the weird exceptions. We spot patterns. We skip the broken instructions. We know which command not to run. We learn who holds the undocumented context. Eventually, the workarounds start to feel normal.
But agents, they don't necessarily build that same durable understanding. They search again. They infer again. They burn tokens getting back to what we already know. We learn about the workarounds and we move on. But the agent just made that cost a lot more visible.
So what do we do? What are we going to do about all this?
They might have something like a platform engineering team or something similarly named. Those teams are basically focused on improving the environment around writing and operating software. They work on developer setup, CI, deployment, internal tooling, making sure we have safer access to production, shared workflows. Their job essentially is to make the environment easier to work in over time.
I was recently talking with Austin Story at Doximity. Shout out to Austin wherever you are.
They've also built an internal skills marketplace so the useful workflows don't stay trapped in one engineer's local setup or prompt history.
Heard something similar from Brian Scanland when I interviewed him on On Rails. He works at Finn. Their team has shared skills that anyone across the organization can use, including people who aren't really software engineers. They built wrappers around things like Rails Console and Rails Runner, giving production agents themselves even more controlled ways into their application. Different company, but similar patterns.
But not everyone works in an organization with the capacity or budget to have a dedicated platform team. Probably a lot of people in this room are not going to go back to work next week and find that you've suddenly hired five people that are just focused on improving your internal developer experience.
Who does this work on a team of say 20 developers, or eight, or maybe only three? Who notices when there's weird friction that keeps popping up and deals with it? Because that work doesn't really just disappear because nobody owns it. These things still need somebody's attention. But who
here is familiar with this gentleman? I see a few hands out there. So for everyone else, this is Q from the 007 James Bond stories. Q heads up the research and development branch for MI6. His team builds the tools, the devices, the strange car features, and this pen that will clearly become important 45 minutes later in the story.
Bond gets the mission. Bond gets chased through the city. Bond orders the martini. And Bond drives the expensive car into the ocean. But Q, he focuses on improving the environment in which that mission takes place.
But engineering culture encourages many of us to imagine ourselves as Bond, James Bond. I had to do that. All right.
But sometimes the most valuable person on the team is the one making sure that the next mission requires less heroism. Maybe they build a safer tool. They shorten the feedback loops and remove a path that nobody should be taking anymore. They make it easier for the next engineer or agent to succeed. And that's really the point of Q's work.
This is one of David's other cars he hasn't posted yet. So the gadget is kind of only an artifact though, but the value comes from what the next agent can do with it.
So when I talk with engineers about this type of work, the same hesitation keeps resurfacing. I was hired to work on features, to close tickets. Or maybe the quieter version is, am
not some friction and you had a hunch there must be a better way. But since nobody asked you to fix it, you just kept moving through the backlog. Sound familiar?
How do you decide whether it's worth spending some time on? Are you breaking a commitment? Are you spending way more time on it than maybe the problem deserves? Or are you learning something that could make this easier for somebody else or something else?
Now, there are plenty of reasons not to take a large reckless swing at something that nobody asked you to touch. I'm not suggesting that you all go out, go rogue, disappear for the next 3 months, and build out some internal developer portal that nobody asked for. That's not stewardship. That's a hostage situation. But spending a little bit of time understanding some recurring friction, that seems pretty reasonable.
I'm here to tell you that you do not need permission to do your job well. If you, your co-workers, or your little AI agent buddies that are trying to take your job are repeatedly encountering friction, it's part of your job to try to alleviate that.
This doesn't have to become some big project. Just name the friction. Find somebody else who's feeling it too. Then improve maybe one small thing and see what you learn.
And if anybody questions you about it, now you have this brand new card to play. You can say, "While I was working on this, our little AI agent buddies kept hitting a snag. It blocked them, sent them into a death spiral, and burned a bunch of tokens trying to find a workaround." Because apparently agents burning money now gives us the argument that we were never allowed to make when it was wasting human.
Now, I'm not suggesting that you all abuse this card, but feel free to take a screenshot of that, or photo of that, and send that to your boss.
So, think about it. What are some of the smallest responsible improvements that you can make that's visible, reversible, and useful to somebody else? Now, you may not own the whole, as I said, workshop, but there's probably at least one drawer that nobody has reorganized since, say, 2019.
Now, I want to add an important warning. I am not suggesting that you all go out from Rails World and start hunting for things to fix. You'll encounter these things naturally, and when something catches your eye, it helps to give that curiosity a little structure.
So before we talk about a few specific things we can do to improve our environments, at least for the way that my brain seems to misfire, it helps to have a framework for approaching this kind of work. Otherwise, it's easy to fall down rabbit holes.
Now, I think many of us are probably very familiar with the classical software inquiry method known as FAFO. To find out, you have to find out. Find yourself sitting at your code: what the hell is this code doing? What happens if I just delete this? Sometimes the fastest way to understand software is to poke it. Maybe not in production.
Now, it has its place, but I've been experimenting with something a little bit more deliberate. I call it WUTS, pronounced "what's." It's loosely inspired by inquiry-based learning, scientific experimentation, and my need to give a silly name to a sequence of otherwise normal behaviors. It stands for Wonder, Unpack, Tinker, and Share.
WUTS is not a problem-solving framework. You're already a solver.
And it begins with that small moment. The code's not doing what I expected. Huh? Two people are describing the same workflow very differently. What? This rake task only worked the second time I ran it. Weird. That curiosity is a signal.
Little ahead of my slides here. When we wonder, it's basically just taking that
just personally irritated by a naming decision someone else made 12 years ago. That last one can save you a lot of time, to not get too focused on.
Think about your Rails apps again for a second. What's one thing that you've encountered in say the last 30 days that made you pause and think, what is this? Don't pick the biggest architectural problem for this example. Just pick something ordinary.
Maybe it's a weird setup step that you always seem to forget to run, a warning that everyone else has been learning to ignore, or a comment referring to a system or vendor that you haven't heard anyone mention during your onboarding, or a timeout set to exactly 47 seconds for some really specific reason.
Then we unpack. And unpacking is where we separate what we assume from what we can actually learn. So we maybe start with a little archaeology here. How did this get here? What problem was somebody solving? What constraints existed back then? Because code that looks ridiculous today may have made perfect sense 6 years ago.
And this is where we need to resist jumping directly from "huh" to "I know how to fix this." So before we change anything, let's gather some evidence. Let's follow the behavior far enough that we can then explain what's actually happening. Look at production, measure it, read the history, find the change that introduced it, do the homework you can do yourself. Then if you still need more info, try to find somebody that might remember why.
But sometimes that original engineer or person may no longer work there. What do you do then? Which got me
willing to be tracked down about a decision that they made in a codebase 5 years ago, at a company they no longer work for anymore? Have you ever done that?
So I ran a very unscientific poll on X and LinkedIn. To my delight, after a little over 200 responses, about eight out of 10 developers said that they'd be willing to help. So maybe take git blame a little further. Hit LinkedIn. But anyways, I still encourage you all to do your homework first. And sometimes that homework tells you that what caught your attention
ess
and quite often people skip this part. Then make the smallest reversible change that gives you some useful information. That's the goal: information. Tinkering does not need to produce the finished solution. Sometimes learning that you were wrong with your assumption is the useful outcome.
And sharing is a step that I think a lot of teams just skip entirely. And it doesn't mean posting on Slack, "Hey, I learned something really weird today." Sharing means turning what you learned into something the next person can actually use.
And there's a lot of ways to share what we've learned. Some of this is writing things down, documenting constraints, recording decisions. But sharing isn't always just documentation. Maybe we build a tool so that nobody has to remember the weird workarounds, or we show somebody else how something works. The point is to put what we learned back into the environment so the next person doesn't have to rediscover it.
Think back to that company from the beginning. They'd experimented with many different approaches over the years, but they hadn't consistently closed the loop. Engineers inherited four equally plausible answers to the same question.
All right, let's say you join a company and you're looking at order.save in your codebase. Seems ordinary enough, except it triggers callbacks which then spawn jobs and broadcasts and auditing and cache invalidation, and apparently updates a warehouse inventory system that nobody mentioned during your onboarding. What the hell is going on here?
So we wonder what actually happens. Then we unpack. We trace the callbacks. We map the side effects. We dig into the details. We do our work, right?
call it, then we share. We've done all this work to understand what happens when we call order.save. Don't just leave that understanding in your head. Maybe we do things like add a Mermaid diagram to put that in the repository, or maybe we at least put a sketch into the wiki. Put what we learn somewhere that the next person can actually use it.
Here's another example. Imagine you come across some piece of middleware that nobody's touched since 2018. It scrubs some Unicode, this is an actual real example we found, Unicode from some incoming request, and it says "remove once the legacy mobile app is retired." You're pretty sure the mobile app was sunset before they even hired you.
after a miserable weekend where we had hundreds of production errors on Bugsnag way back in the day. Okay, that's a little bit more interesting than what the comment suggested.
Then we tinker. No, you don't delete it immediately. Maybe we add a little instrumentation or we add some logging and we wait, and a week later we find out that it's fired 41 more times. None of them coming from a mobile app that had actually been sunset. They're coming from a crawler in one of your partners' webhooks. Hm.
Maybe nothing about the behavior changes, but the comment does. Now the next person knows why it still exists and what still depends on it. That's a useful outcome, because not everything old is wrong. And the goal isn't to eliminate every piece of weirdness in our codebase. The goal is to distinguish intentional weirdness from forgotten weirdness.
Again, you don't need to go looking for a bunch of these things. And the tricky part is you probably stop noticing some of your own works. They've just become part of how you work. But you can probably spot somebody else's dos. Watch somebody else work within that
environment. Sit with somebody or pair with them, whatever, and watch them as they work on ordinary tasks. Resist the urge to jump in and just help them or tell them how to do it. Just observe. Watch. They might not know how to notice their own quirks either.
Where do they pause? Where do they repeat? What do they seem to be avoiding? Where have they developed their own weird workarounds? And watch your agents and their agents, too. Or your agents. They haven't learned your quirks yet.
Quick sidebar. Q would never send anyone out empty-handed. So, there's a little something in your swag bag for Monday when you get back to your workshop. But before you go back to your workshop, imagine for a moment that you weren't going back at all.
I like to use this exercise when I'm trying to understand where undocumented context is going to be your last day working on your application. You're leaving. You're never coming back. We don't need to get into why. That's between you and HR. But you need to write a letter to your replacement.
Can you do that in DHH's Keynote app yet?
Dear replacement, welcome to the party. This is mostly a normal Rails application except dot dot dot. You answered that too quickly.
What's weird in your apps? What parts would you warn them about? Which command should they avoid running? What areas depend on context that you know damn well is not written down anywhere?
And for extra credit, ask a few of your co-workers to write their own letter. Then compare. Do they warn about the same things? Does one engineer know about a constraint that nobody else mentions? Because what you're writing down is basically the oral tradition your team has been carrying around.
And there's probably something useful hiding in that gap between what the application says and what the team knows. That gap is also part of your workshop.
Now, we recently conducted the 2026 Rails Community Survey. Thanks for those that participated. Survey results coming soon. And we asked people where people struggle most when joining an existing project. And the answers were pretty telling.
Number one pointed to understanding the domain model and the business logic. Two, understanding old or inherited code. And three, a lack of documentation. Probably not that surprising. There's a theme here. The struggle isn't necessarily figuring out how to write the next piece of code. It's understanding the system that they've just inherited.
And none of that's probably surprising, but it tells us where to look. Places where shared understanding is weak and rediscovery is expensive. So where should we invest our time? I think these improvements kind of fall into three broad categories.
First, make the path obvious. So, suppose your team is regularly adding integrations. One approach is to tell people, find the most recent one and copy that as inspiration, which is great until that was an experiment.
Or you can encode what the team has learned into something like a generator, one that can create the expected class, configuration, error handling, fixtures, stubs, documentation, whatever belongs in every one of those integrations. That decision then becomes executable. Humans can use it, agents can use it and reviewers recognize and appreciate the consistency.
Because a repository instruction says this is how we work in the application. And a canonical example says this is the one we're currently meaning. And a generator says start here. They all reduce the number of plausible choices, but the generator goes one step further. It gives you a starting point instead of having to ask you to interpret one. This is Rails-style leverage applied to your local workshop.
And as for agents, at least I'd like to try to think that I'd much rather give them a generator that reflects the team's current expectations than to ask them to search the repository, find 242 plausible examples, and then have them synthesize a 243rd. But maybe agents are just going to work around this anyways.
Second, let's make feedback fast and trustworthy, because fast feedback that lies to you is not helpful and slow feedback that everyone just ignores isn't helpful either.
Every engineering environment has these hidden user manuals where nobody really wrote them, nobody reviewed them or approved them, but everyone learns them. You learn to stop running the full test suite locally because it takes too long. You learn that staging is rarely that reliable. You learn which warnings everybody seems to be ignoring. Nobody wrote those rules down, but the environment taught them.
And agents, they just inherit that same hidden user manual. They still have to wait on our CI. They still have to decide whether a failure actually means anything meaningful. Because when we attach a fast coding agent to a slow, unreliable feedback loop, it's still having to operate inside of a slow, unreliable system.
So, where is everybody waiting? What takes 40 minutes that might only need to take five minutes? What errors send people searching through weird Slack threads? What feedback arrives so late that you've already moved on to the next thing?
Not every check needs to be instantaneous, though. Some probably should take some time. Some should probably happen a little bit closer to production. But the goal is to get the right amount of feedback at the right stage of the work that you're doing.
Now, earlier I talked about Q and how maybe improving the environment around the mission. But there's another version of that idea that hits a little closer to home for me. While I am a musician, I think that maybe in another life, being a guitar tech would have been one of my dream jobs. When I was younger, I wanted to be the musician on stage, but I just ended up here on stage.
But these days, I can really appreciate the person making sure that the musician on stage can do their job, because techs needed for the next song. They're tuning its stage. If something starts to go wrong, they're already nearby trying to help figure it out. And after the show, they're fixing whatever caused problems tonight so that hopefully nobody has to deal with them again tomorrow. They're constantly tending to the environment around the performance.
And at first glance, sure, they're working for the musician, but really they're working for the audience, and ultimately that's who we're working for, the people using our software.
The third category: make mistakes cheaper to reverse. Notice I did not say prevent mistakes, which is a lovely ambition but a terrible operating model. How often does your team say, "Let's find out"?
If every experiment feels irreversible, guess what? People stop experimenting. Not because they're lazy, because they're managing risk. When mistakes are cheaper to recover from, people might be more willing to explore.
We've seen how this stopped happening. One deployment, one migration, one forgotten config file and suddenly three engineers are debugging production for the next few days. The mistake was not the expensive part. Recovery.
And after a few incidents like that, the team learned something. Be careful. Don't touch that. Get more people in the room. Let's wait till Monday before we push that out. That fear becomes part of our workshop.
So part of improving the environment is changing that calculation. Feature flags, reversible migrations, preview environments, smaller deploys. These are all ways to give ourselves somewhere safer to be wrong. They do not eliminate mistakes. They simply make recovery cheaper. Because when recovery is cheap, you will explore. But when recovery is terrifying, you learn to stop touching things.
And across all three categories, there's one more thing we can do. Reduce obsolete choices, because every abandoned pattern that is still there is teaching, well, this is one way we do things around here. It changes what the system teaches.
And as engineers, we tend to think that leverage comes from adding something. Sometimes it comes from removing something that nobody should be using anymore. Deletion is an architectural decision.
And sometimes improving the workshop means building a tool. Yeah. Sometimes it means labeling a drawer. And sometimes it means documenting why that one weird tool still needs to be there. The goal is to make the preferred way a little bit more obvious to whomever or whatever comes next.
That company at the beginning of this talk, they needed an outsider and some experts to identify the right architecture, but there probably wasn't a perfect answer. But there was a choice that fit the system that they had now well enough to document, test, generate, review consistently, and improve upon later.
What they needed was somebody willing to say, "We've learned enough from these experiments. We're doing it this way now." Not forever, just long enough to stop making the same decision independently every time.
And this thing, I think, might be happening inside of your code bases, in your workshops. You're working inside of decisions made for different moments. Some probably still fit, but some were temporary. Some were accidentally left around by a former coworker. And years later, there's nothing really telling you which is which. Again, they're unfortunately all still written in that same damn font.
So, when something makes you pause, I want you to pay a little bit more attention to that. I want you to follow that curiosity. I want you to follow the what the understand.
And when you learn something useful, give the next person somewhere to start, because somebody else is going to end up in that part of the code. They might join in 6 months or they might be an agent that shows up tomorrow morning with none of your accumulated workarounds.
Again, we don't always need to be Bond. Sometimes the valuable work is to be Q, to put a better tool into somebody else's hands to make sure the next mission requires a little less heroism.
Because the engineers who create the most leverage won't just be ones producing more inside the workshop. They'll be the ones improving it. Thank you.
Article published
