Tag: management

  • Escaping the No-Code Platform by Building a Software Factory

    I’m not someone who gets called when things are going well. So when Michelle – the Twill CEO – called me in December, it was because she needed some help with engineering. In 18 months of being an advisor, this was the first time it was a phone call and not an email.

    There were a lot of things going on, but at the core of it was the data model, which was starting to really hold things back. The data layer was more like CSVs than a proper relational database. The no-code platform was good for getting to product-market fit, but it was clearly hitting its limits.

    Twill is a two-sided marketplace focused on hiring – flipping it from high-volume, low-signal to a low-volume, high-signal model. Companies can post jobs, and members can refer their network to jobs with personal recommendations, and get paid for placing people. I had been a hiring manager in the agentic era, inundated by applications from agents, trying to sift through and figure out who would be good at a time when it seemed that every interviewee was extensively prepped by AI and giving bland answers. The idea of using human networks and knowledge about who actually does a good job was – is – compelling.

    My first job was to rationalise things a bit (no more two-way writes between Bubble and Airtable) and then get it to a place where the business could function on it whilst we moved to a more normal setup – one with a proper database. That took our one full-time engineer until April, at which point I was able to increase my hours.

    I knew agentic coding could speed things up – I’d just got started with making a slightly unhinged side project that I never would have prioritised before Claude was a good frontend programmer. My previous team had been using AI code reviews since early 2025. I could see the utility, and some of the potential, but I had no idea how to estimate in this new world. I wrote a migration plan, textbook, the way we used to – decompose things carefully, derisk, run things side by side.

    This is a story about how we threw that plan in the bin and shipped a full replatform in four months.

    This is also a story about how I went from running an 80+ person team to running a software factory. Many things have changed, but it turns out that running a large team was a better setup for this shift than I thought.

    In my previous life, I was one level below VP at DuckDuckGo, responsible for roughly half the engineering org – mainly client (iOS, macOS, Android, Windows, C++ with some Frontend). My background is in native application development. Now, it’s me, and one other engineer, building a Node.js app on top of a Go API. I am – somehow – responsible for all our AWS and other infrastructure.

    The challenge of the V2

    V2s are notoriously difficult. I know, because I was the kind of leader often dispatched to take the failing V2 project and get it delivered. Amongst other things, I’ve led teams responsible for delivering text editors and web browsers – incredibly complex applications where reliability is fundamental.

    If “underpromise and overdeliver” is the rule to live by, V2s are where that rule most often falls apart. V2s are systematically overpromised and underdelivered. Because why build a V2 if it’s not going to be better than what you have currently? But also, replacing what has been built up over a period of years is incredibly difficult.

    V2s fail because it’s so hard to define the scope, and stick to it. Because it’s easy to align people around a dream that will deliver everything everyone wants (eventually), and much harder to deliver according to a strategy where everyone is going to be explicitly disappointed on some shorter-term timeframe.

    The old platform was functional, but expensive to run, especially the kind of data work that was critical for an efficient user experience. The structure of the data was fundamentally incompatible with the kind of AI roadmap every startup is tasked with delivering.

    First, we stabilised the old platform and made sure critical functionality for business operation was in place. In April, we started building a new system. We started with a list of API calls for each screen, and the DB model backing them. This was foundational information for a rebuild, and relatively efficient to extract. On top of this information, I focused on infrastructure – building a design system, and a Go API – whilst the other engineer worked screen by screen, rebuilding the platform.

    The first decision we put in the bin was running the backend on AWS, and instead running it on Render with the database on Neon. The complexity of AWS was just not worth it for such a small team, and the cost savings – if any – were marginal. This was a big unlock, because instead of futzing around with Terraform, in a couple of days we had everything running end to end. We kept AWS for S3 and can move to it at a later date should it become worthwhile.

    The second decision we put in the bin was the side-by-side operation. This came back to the data model, which I’ve been comparing to putting your to-read pile in a library system. Painful, and obviously a one-way door. You can’t run both systems side by side when one of them runs on a database and the other runs on a jumble sale. At this point, it was clear that we would deliver less incrementally, and less safely, than I had planned or would want to.

    The third decision we put in the bin was the launch date. We had no idea how to estimate, so had picked July 4th as a suitable date – what better time to take the site down than when the user base is having a long weekend? We were basically feature complete then, but given the one-way door of the launch, we pushed back about a month (to August 2) and spent that time on data migration, cleanup, and hardening.

    All this time, I was saying no to every feature request, and every bit of scope creep. Michelle put me on blast on LinkedIn. I held firm. You can only say no for so long though. We really needed to ship.

    On August 2, we shipped. That week had some firefighting, but our hardening and process period paid off. The worst thing that week was a number bug – cents as dollars. Which, whilst embarrassing, at least wasn’t anything safety critical given the extent of PII in the platform.

    Leaving the no-code drag-and-drop style platform is always going to be hard. What’s interesting to me is that it’s now possible. The replatforming was obviously needed, but how do you possibly do it with two people, one part time? How do you justify the cost to the business? Claude made the math make sense, and the software factory model meant we could ship in four months.

    Building the factory

    I was doing what I used to do – paying attention to what was working, what was not, how problems slipped through. I set up infrastructure, CI, prioritised work that eliminated problems. I built process, but this time in the form of skills rather than spreadsheets or checklists. Together, my teammate and I built a software factory.

    Michelle always used to tell me one day I would be her CTO, and I always demurred. I didn’t think my skillset was what she needed – I thought she needed someone who had more experience in web apps and backends and infrastructure. Someone who had more of a tech lead manager mindset, capable as a people manager, but keen to still write and ship code. Turns out, she was right and I was wrong. I am not the profile I would have recommended for her before the agentic era, but I was well suited to build a software factory. Managing 80+ engineers, I didn’t write the code. I built the team that wrote the code, and the processes that made them effective.

    One of the differences for native application teams is that we’re not typically supported by shared service teams. “Infrastructure” and “SRE” teams usually focus on supporting backend and web. We build our own CI systems, do our own releases, and handle our own incidents.

    Whilst feature teams tend to be divorced from the underpinnings of DevEx and reliability, we are not; we build them ourselves. We also tend to feel the cost of problems much more acutely – in part because of this, in part because of the feedback loop of the app store ratings. As such, I was used to owning and iterating on quality issues. It had been my job – admittedly in a very different context – for years.

    I was on a learning curve, trying things, asking questions, seeing why things didn’t work the way I expected them to, and iterating. Eventually I ended up at orchestration.

    Orchestration was a result of DDoSing myself. Too many things in flight, flitting between them, nudging them along. So many terminals I needed to colour code them in order to tell which was which. Burning CI minutes on collisions.

    The trap I fell into is that the cost of generating drops, and you can have a lot more things going. Just because you can doesn’t mean you should. Instead of nine direct reports, I had nine terminals. But similar to having that many direct reports, the level of attention needed by each varies, and a system for that helps apportion focus.

    Orchestration was part of fixing that, living in three terminals:

    • Terminal one – sequential focus on things labelled “needs human”.
    • Terminal two – the orchestrator, 3-5 PRs in flight at any given time.
    • Terminal three – the merge queue, final validation and integration.

    This unlocked momentum, and with that momentum more guardrails became necessary – and also cheaper, because a lot of that kind of work is mechanical and well suited to orchestration. I know there’s debate about the utility of PRs, but I still believe PRs are useful. The PR itself is a queryable unit over which you can run rules and reports.

    Having hit momentum and feeling happy with the system, Jean – my collaborator on DRI Your Career – wanted to try it. So I retrofitted a couple of months of learning onto another platform. Jean and “intern Claude” had mostly built it. It was time for Claude to be promoted from intern to engineering team.

    I used to scale teams over a period of years. Here, in a week I put in:

    1. A release branch and release process. This would have been overkill – a bit anal – for two people, but it’s the natural progression for a team no longer wanting to deploy every PR on main. I know this goes against conventional wisdom, and you can probably see my background in native app development here, but for a two-person team with no on-call SRE, better to schedule your problems for a convenient time.
    2. The AI-native piece (orchestrator and merge queue). Which also lets Claude work overnight while we’re sleeping and don’t need the tokens for everything else.
    3. Board hygiene – P0/P1/P2/P3 aligned with orchestrator + merge queue. The board setup of a well-organised 6+ person team, which keeps the orchestrator (and us) focused on impact rather than maxing out token and CI spend. Features slated for the next release get tagged – I brought this in when I realised we could easily ship >50 PRs without a finished headline feature.
    4. DevEx and optimisations – ephemeral DB targets, authenticated E2E tests, env var requirements, a full design system, automated nightly DB backups. Things we hadn’t needed when validation was manual, but that are helpful to have in place before leaving an AI unattended. A level of DevEx I used to watch 20+ person teams struggle to reach, which I actually consider not over-engineering but necessary to support the velocity.

    It used to be the case that there was a 2-5 person team process, then the 6-10 range, then the 20+, the 100+, the 1000+. Managers got hired in part to deploy the playbooks that moved teams through those ranges.

    All but one of these are things I’ve done as part of scaling a team in the before times. I just didn’t use to do them all in a week. This was the moment I realised that the playbook is not gone – it’s reconfigured. Smaller teams have everything they need to be effective with agents, because almost all of it is stuff that bigger teams used to put in over time.

    I have heard managers say this shift doesn’t impact them the way it impacts ICs. It does. Even if your process was right-sized for your team before, it isn’t – or shouldn’t be – once each person on your team is running a team of agents.

    Quality control

    Like many software engineers, I’d noticed how much worse software seemed to be working overall. I’d seen the gaps in reasoning that happen between Claude and humans. Claude reasons about code. Humans reason about what is in front of them visually. It was clear to me that quality control was critical.

    As engineers, we plan what we expect to build, and we expect some work to come in to maintain it. Incidents, bugs – the second roadmap. The one we don’t write down, except when we’re explaining why the first roadmap wasn’t fully delivered.

    We’ve all seen the news about Meta’s plan to replace staff with AI, and how it was scaled back. Their own data shows that whilst code changes to internal platforms and infrastructure went up 220%, there was only a 36% increase in changes reaching users. That’s comparable to the increase in major incidents – 40% – and the time spent firefighting them went up 70%. (Reuters special report, Katie Paul and Jeff Horwitz, 26 Aug 2026)

    Increased output is not the problem. The problem is how to turn increased output into business value.

    Which brings us to guardrails. I’m hearing this word a lot, but it rarely includes a definition. Here’s mine.

    A guardrail is a way to prevent problems.

    This is intentionally broad, because what constitutes a sensible guardrail varies. We’re talking about them a lot because that has changed so much in the agentic era.

    Large companies always built layers so people could operate with partial understanding without creating catastrophic problems. The practices always existed. But smaller teams relied on things like “tribal knowledge” or “only hiring seniors”.

    Automated code reviews were of course an initial guardrail. I quickly learned that putting things in skills files was good, but not sufficient. For robots, like humans, written good – automated better. I became fascinated with what percentage of output should be guardrails.

    The good thing about guardrails is that they are often quite mechanical, and once I had a good orchestrator and merge queue set up, I could throw that kind of work into it more easily. I would use my oversight – noticing problems, additional PR reviews, the things that almost shipped but didn’t – and extract from it the preventative work that could be dispatched via orchestration.

    This was also a benefit of building from scratch. Legacy codebases contain competing patterns and ideas, and half-finished migrations. In a new codebase, we can decide: this is how we build. With agents, we can fix the mistakes we made as we spot them.

    This is where I think the drive for hands-on managers actually has value – because the volume comes faster, and you can’t evolve these checks in post-incident reviews any more. You have to be on them constantly. If no one writes the code and no one reads the code, how do you figure out what is needed before the incident?

    The chart below shows our guardrails evolving over the course of the build. Starting with written-down instructions, and increasingly automated over time. Because it turns out, agents also don’t always RTFM.

    Despite “changes must have tests” being in CLAUDE.md from day 1, that didn’t reliably happen until test coverage was instrumented and a required check. The .md rules and automations are not divorced from one another; they can reinforce each other.

    • Mandating 70% test coverage doesn’t mandate quality of tests – enforcing mutation testing in the orchestrator does that. Every agent must “break the fix, show a named test fails, restore, show green – and put that evidence in the PR body.”
    • Every diff gets asked “does any check here report success without verifying what it claims?” Before a PR is bounced, a second independent agent re-verifies the finding from file:line only.
    • Any bug that reaches production requires both a regression test and a monitoring alert.
    • An agent hook, block-migration-merge.sh, stops Claude merging any PR that touches a migration – these changes are hard to roll back and can impact the integrity of the data, and so a human needs to take responsibility for them.

    Before, the discipline was: you found a bug, you wrote a test so it wouldn’t come back. Good practice. Now, I do that, and then I ask: how do we guard against this class of problem? Because competent humans rarely make the same mistake twice. AI will make the same mistake endlessly.

    Making a class of issue impossible is not cheap. This is why we didn’t use to do it – we relied on the incident postmortem and code review, and the visceral shared memory of the team about that time we messed up. Now, a minor bug spawns five-plus follow-ups – graduated solutions of increasing complexity.

    For example:

    • Aug 26: the internal candidate drawer passed user_account.id where candidate.id was expected. Both integers – so had they collided, it could have silently loaded and written another person’s data. Staff-only, caught by an alert, and fixed within hours.
    • Aug 26: named the class – “silent wrong-entity resolution”.
    • Sep 2: ID-space collision detector; test-DB sequences offset so the two ID spaces can’t coincide in tests.
    • Sep 23-26: typed IDs at the sqlc boundary – passing the wrong ID is now a compile error. Closed Sep 26.

    This is the rigour needed to remove classes of problems: fix the instance → name the class → detect it → make it impossible to write.

    Another example, the currency bug launch fire – members seeing $500K bounties when it should have been $5K, uncaught by all kinds of tests (and human review):

    • Aug 4: class – dollars in one place, cents in another.
    • Aug 5: detect – a visual snapshot guard on the bounty display.
    • Aug 5: make it impossible – one money module (money.ts) and a branded Cents type, so passing a raw dollar amount is now a compile error.
    • Aug 5: guardrail on tests themselves – a test value must be one the system actually stores, never one reverse-engineered to make a formula pass.

    Observability is good. Self-healing is great. But: the bug that never ships is better. This is the whole point of shift-left. Building in a way that is testable, and actually writing those tests.

    The most useful guardrails are architectural. Startups were always about shipping just good enough as fast as possible. But now architectural decisions can support – enable – speed.

    As engineers, we use a lot of words to talk about architecture, but at a fundamental level, architecture is about making good decisions easier, on a timeframe you can reason about.

    An architectural decision I made at the start was Role-Based Access Control, RBAC. It was an expensive decision in month 1 – and vindicated in month 4.

    In the old times that would have been too expensive to justify. We’d had a lot of churn there, and it was somewhere I thought it would be important to be able to add new types, and move things around – one line in a table, and hasPermission() now returns true.

    One of my colleagues told me the access model was now stable. What would I have said if I had to justify a detailed roadmap? “I don’t believe you?” Hardly conducive to good working relationships.

    As it was, we could deliver the architecture underlying the features without debating the value of it. And when the permissioning model changed – which of course it did – that work paid off, making it less painful.

    An architectural decision that surfaced over time was the SQL. It started as a bug: NULL-scan 500s – a NULL in the database reaching code that didn’t expect one.

    • Jun 17: fixed the instances, tripwire in CI.
    • Jun 18: a ratchet guard stops new hand-written SQL.
    • Jun 18-30: moved the handlers’ hand-written SQL onto sqlc-generated queries. That was ~40 PRs – previously an untenable amount of work for something that could be caught in review.

    These choices would not have been justifiable in a pre-agentic-development world. But in an agentic development environment, I have seen the impact. Areas of high churn and potential complexity deserve more attention, and more conscious architectural design. The win is seeing fewer problems than you’d expect.

    Gates before humans

    The shift to orchestration also shifted responsibilities between Claudes. “Dispatch a review agent” was encoded in our process for months. It’s very helpful. But I would still find the odd issue or untracked follow-up. The merge queue was the answer to PR collisions – it serialises merges across concurrent sessions, files the follow-ups, and sends PRs back when they’re not ready.

    The next round of reviews I dispatched came back clean. And the next. And the next.

    Turns out merge queue Claude, reviewing work it had no part in, was stricter than the Claudes that had done the work. It had value beyond the mechanical sequencing. 

    The final quality gate is the release process. It’s easier to have one bigger gate before releasing to users than hope that every PR got the requisite attention. As part of that gate, we use Chromatic visual snapshots to ensure everything that has changed visually is flagged. We also have some extra checks on database changes going to prod because – this is where it all started – data quality is critical to the functioning of the business.

    Even if we run a software factory, the first time something meets a human should not be in production.

    The evolution of the factory

    Here’s the arc of how it went.

    Note: this output is two engineers; we had an intern for six weeks in July/August.

    We got started in April and May, really hit our groove in June. In July, we were effectively feature complete and spent most of the month preparing for a smooth launch – ensuring our infra was all set up, and doing a ton of work to migrate all the data safely.

    August was very reactive. The launch went okay, probably about as well as moving off a no-code platform could have. We did about ten hotfix releases. The real fires were two days at launch – a 500, an SSR crash, and the currency bug. Was it my smoothest launch? No. It was never going to be. It was acceptable. 

    In September we came back to having more of a roadmap and delivering bigger features that we couldn’t on the old system, such as a live revenue and metrics reporting page. We also expanded our top of funnel flows for both members and companies, as well as integrations that allow hiring teams to work where they usually work, such as Slack and Ashby. The rest of the output is mostly the second roadmap. In September, fixes were over a third of merged PRs, which includes polish and iteration on things we’d just shipped as well as bugs.

    In the end, my answer to the question of what percentage of output should be guardrails is around a third. This was my intuition, and it aligns with the data. Note that this isn’t human time, because so much of this work is quite mechanical.

    This doesn’t just show up in the percentages. In September PRs got harder to land – the share landing in ≤2 commits fell from 67% (Aug) to 53% (Sep), and median open time rose from ~1h to 3.5h, partly driven by queue contention. But output was still up – 779 PRs – and September had just one hotfix release.

    Operational costs

    I had never thought that much about CI before – that was something done by someone who reported to someone who reported to me. But I’ve been spending a lot more time on it, optimising things. We talk about token spend, but those tokens also generate CI minutes. And the more rigour we put onto our CI – where it should live – the more that cost goes up.

    In September our CI spend was higher than our AI spend. This was in part thanks to the Max plan (this would not be the case on API metered usage), but also the ability to run the factory during quiet periods – like weekends and overnight – when we don’t need the tokens for everything else, and CI provides the guardrails whilst humans are resting.

    I like to split our running costs into base and velocity costs. Base is the cost of running the platform; we’re paying that either way. Velocity costs are a function of output, so they should look like good value against what we’ve delivered for the business. August was our first full month live, and velocity cost (excl. Claude) was about half of base.

    The number of guardrails is not the goal; the outcome of reliable software is. Everything needs to add value. I check at least monthly that this is the case.

    Running the factory

    Scaling a team, you keep coming back to the principle of clarity: be clearer. Clearer about what’s expected, who owns what, what good looks like.

    I had a model of engineering management with four layers. None of them went away. What changed is how fast each one moves:

    • Mission – the purpose of the team. Still basically the same.
    • Strategy – how the team expects to deliver on that purpose. It needs to be more alive. Think in weeks not in quarters, or in quarters if you used to think in years.
    • Tactics – the process layer, what makes teams interoperable and observable. It used to be written for humans, took months to land and needed change management; now it’s written for agents, lands the same day and is enforced by machine.
    • Execution – getting sh*t done. It went from today or this week to overnight, continuously – the dark factory.

    With two developers, our output is high, but we’re still bottlenecked on the bigger feature pieces. Those we single-focus. Generally the way we work is:

    • Engineer: one large feature + data work.
    • Me: one medium feature, releases, other CTO things (sometimes making slides for VCs and sometimes being the IT department).
    • One standalone orchestrator cranking through the backlog.

    This means the bigger features still need to be prioritised. They need human attention.

    Michelle, our CEO, is non-technical. She only asks for features – that’s her job. The guardrails so she can have those features are my job. I said no to everything for four months, because I knew the velocity win was leaving the no-code platform and I knew scope creep is the killer of the V2.

    The best day for me wasn’t the day we shipped. It was the day she asked for something and then mentioned later “oh it’ll be so good when the platform has this…” and I told her it shipped that morning.

    When execution gets cheap, doing everything is tempting. But doing everything isn’t a strategy. With the factory model, everything comes back to rigour. What is most valuable, in what order, still needs to be clear.

    There’s this dissonance around “go faster” being a strategy. It’s not a strategy. It was never a strategy. Similarly, “just AI it” was never a strategy; it was a forcing function, a blunt instrument, to find the limits. The person who gets paged when those limits are breached, or the person who has to clean it up when it’s wrong, was never going to be on board.

    But to say “just AI it” isn’t a strategy is easy and obvious. Replacing that with an actual strategy is much harder. Here’s what my strategy looks like today:

    • Every question I have gets an answer. I used to be judicious about this, because every question I had had a human cost. Now I can – and do – ask Claude all my questions until I am satisfied.
    • Human communication is AI-augmented, not AI-driven. I spend more time iterating on and reviewing specs for human agreement than I do the PRs that will be produced from them. But the spec is how we ensure we’re building the right thing, well, and it’s the thing that I give to other humans to review and sign off on. It’s critical.
    • Everything is in writing in a shared place (skills, CLAUDE.md), and if it can be instrumented effectively, we instrument it.
    • We put in checks that allow us to be accountable for work we didn’t produce, and gates where humans explicitly take responsibility – migrations and releases.
    • We find non-human ways to surface problems. CI data is a rich source – how long PRs spent open, how many times CI needed to run. Code coverage reports tell us where the gaps are. I’ve built practices (habits and skills, mainly) to check in on this regularly, find the bottlenecks, and figure out how to improve them.

    Retrofitting the factory

    Building the software factory from the ground up has been fascinating, but the real challenge for the industry is how to retrofit it to existing engineering teams. This is vastly more difficult. 

    Managers encode judgement through process and relationships. Relationships build judgement 1:1 – and that’s valuable – but process is how judgement scales. If you want to move at speed with these new tools, you can’t have eight people on the team moving as fast as possible and one person trying to figure out how to make them collectively more impactful. You certainly can’t expect that from the person who has so many direct reports they can’t physically meet with them each week. Every IC needs to learn how to do it for themselves, and then collectively, so the team can move faster together.

    ICs aren’t being asked to do this. They’re being asked – told – to go faster. But clarity and good process are how teams go faster. This is the work good managers always did. Now managers need to scale that work earlier, with people who didn’t deliberately sign up for it, and who feel threatened by the idea that the skills they invested in for so long may be less necessary.

    Having done both, this is where I would start:

    • Prioritise skill building and knowledge sharing for fleet management, because ICs are used to managing their own output and this is a different perspective.
    • Rebuild guardrails for the agentic era – historic incident postmortems likely contain ideas of where to start.
    • Find non-human ways to surface problems so you can proactively coach ICs on thinking one level up. Fill in platform health gaps, and set up engineering effectiveness checks – like PR open time and CI spend.
    • Separate human work from agentic work and be clear about which is which, and why. We don’t get business impact by DDoSing other humans with long, half-thought-through documents. 

    Choosing chaos

    When the industry was being upended, I chose to go live in the chaos because it was clear to me the chaos was coming for all of us. That coincided with feeling it was time for me to do something different, and honestly, I’ve been having a great time.

    How we work is one thing, but I’ll write this one day and it will be different in a week. It’s easier to measure progress than state. This is why I have all the data – it helps me see, amidst the volume, what the impact is, how we’re achieving it, and what is slowing us down.

    Scaling and running large orgs, rigour was my job. That piece hasn’t changed. The rigour is what creates progress. Escaping the no-code platform is the unarguable part – there is no way we could have done it without Claude, and also, no way Claude could have done it without us.

  • What do managers even do now?

    Credit: Paul Hudson / Wikimedia

    I watched an IC have a lightbulb moment: they’re a manager now. Running agents in parallel, giving direction, deciding what’s worth doing. Being responsible for what ships, without doing it all themself. My job is giving them the pieces of management that are useful right now.

    Not how to run a 1:1.

    How to think one level up, and systematically. Not the bug, the bug class. Not the problem directly in front, the one that comes next.

    The ones asking for this help are the ones who still feel responsible for what ships. How do I do this responsibly? I see pro-AI-development and cognitive surrender being conflated as the same position. They aren’t. The work is building systems where you can be responsible for what you shipped without being in the details of it.

    ICs spend – or at least used to – more time focused on the thing immediately ahead and as such are biased to notice that. It made sense when that took a while, but now it can be faster, the timelines are compressed – or they can be, if things are working well.

    Managers encode judgement through process and relationships. Relationships build judgement 1:1 – and that’s valuable – but process is how judgement scales.

    Scaling agents has really tapped into something for me, and it’s all the skills I used to use when I was scaling teams – many of the same ideas showing up at different times. Also things other people used to do and I never got into the depths of – I’m spending a lot of time in CI, lately. I never did that before.

    The human parts of management are important. Of course they were. But the people who thought managers did nothing but go to meetings always seemed to miss the pieces those meetings (and documents, and nudges, and questions) moved forward. Which was finding the things that were lossy – whether partial processes, or missing guardrails or understanding – and causing them to be filled in directly or indirectly.

    If you want to move at speed with these new tools, you can’t have 8 people on the team moving as fast as possible and one person trying to figure that out. You certainly can’t expect that from the person who has so many direct reports they can’t physically meet with them each week. Every IC needs to learn how to do it for themselves, and then collectively, so the team can move faster together.

    Management is learnable. When you scale a team you build a layer of management underneath you. You bring people in, or you lift people up, and you train them. You take the values of the team and encode them into process, because process is how you get multiple people to do the same thing consistently.

    ICs aren’t being asked to do this. They’re being asked – told – to go faster. But this is how teams go faster. This is the work good managers always did. Now they need to scale that work earlier, with people who didn’t sign up for it deliberately.

    If we’d ever really been clear on what a manager does, perhaps this aspect of management would be more defined and it would be easier. Oh well.

  • The Date – Blunt Implement or Forcing Function?

    Credit: Alexas_Fotos / Pixabay

    On some of the worst run projects I’ve seen, leaders trying to get them back on track would set a date.

    Never, ever, in that circumstance, have I seen a date be met. No-one believes in it, no-one is willing to work overtime to meet it. It slips. Another one is set. And another. Maybe six months later something goes out.

    I feel conflicted about this because I do really believe in the power of setting a date as a goal. The thing is, for this to work:

    • It needs to be part of the conversation from the point when the project is defined and real.
    • It needs to push people but they have to be able to reason about and with it – it can’t be a joke.
    • It has to be used as a way to force decisions – what’s in, what’s out.
    • It has to be part of a healthy function where in general bottlenecks get investigated and removed.

    We just shipped a complete replatforming for Twill, and this is how I approached it. I set a date – July 4 – because honestly what better time to ship a big thing than when Americans are OOO and partying. The engineer I work with told me I was wrong – and I was – we shipped a month later, on August 2.

    On the one hand – one month overdue, 33% of the plan. On the other hand – four months. This required us to be brutal – as the CEO puts it, I said no to every request for four months.

    You can only say no to everything for four months when you have credibility and you’ve given people a baseline first. You can only keep that up for so long – you have to ship.

    This might seem basic, like yes, this is the thing we’ve all agreed on for a long time. Maybe you want to cast some shade that I was off by 33%.

    But here’s the thing – whatever we had thought we’d agreed, AI has upended it. More and more the date isn’t a month out. It’s today.

    A week out. A month out. Far enough away to seem possible without knowing what actually needed doing. Reality would arrive. Eventually they’d stop.

    The leader who sets the date today is sometimes right.

    It took me a while to set a date at all. My stance was that so much had changed that my way of estimating was off base. I’m not surprised I was wrong – I know exactly what was faster and what was slower than I had accounted for.

    As I write this, some Claudes are working. One of them is cutting a release. Another is running agents and churning through a list of issues. This is completely different. But I will still need to validate the release before it goes live. And later I’ll come back to yet another Claude and figure out what else is ready to go, what needs human judgement or setup. That bit is less different.

    The discipline of decision-making, of reducing collisions and churn… that continues.

    There’s this dissonance around “go faster” being a strategy. It’s not a strategy. It was never a strategy. But I see engineering pushing back from a stance of, I thought we agreed this was bonkers? We have to come at it by reasoning about what has changed and what has not.

    For years, in engineering, we’ve worked to make the conversation about velocity rational. Now we need to do that again. Even when “go faster” is the strategy, turning engineering – now with additional token spend – into impact is still the job.

  • What would make next week better?

    Credit: Flickr / Christopher Bowley

    Just about everyone gets overwhelmed sometimes, and many of us deal with that by working harder. This is a reasonable response to a single unexpected thing, or a bad week, but it’s not the right response to systematic overwhelm. Then you need to stop asking the question “what do I do next” (or worse: “how am I going to do everything?!?”) and ask a different one:

    What would make next week better for future-me?

    When you’re overwhelmed, current you is SOL. Future you doesn’t have to be. What can you do for them?

    Working harder isn’t the answer, and you know this because if it was going to work, it would have by now. Also you can’t operate at your max capacity week in week out, because something will happen. You’ll get tired. You’ll get sick. The vacation you booked months ago will suddenly be next week. Something will go wrong. Your exec will demand something you hadn’t accounted for.

    When you’re overwhelmed, thinking about future you, and picking one thing, small enough that you can do it while still drowning, is how you dig out of the hole. Maybe the first one won’t feel like it made a big difference. But enough of them, and it will.

    The bonus: this isn’t only a way out of overwhelm. It’s how you build slack, so you have capacity when the opportunity comes, or the unexpected bad thing does.

  • Useful AI skills for Engineering Leaders

    The volume is up. More PRs, more pings, more incidents, more asks coming from more directions. I used to have 8 directs that dealt with most things, and organized and routed information to me for what I had to help them with, but since embarking on a new adventure, I’ve been rebuilding a different system that helps me stay on top of things and prioritize it.

    Three jobs, in order: 1. route the tedious stuff so it doesn’t waste my time, 2. report usefully so I can orient quickly, and 3. understand what’s actually going on.

    These all run on Claude Code as part of a broader chief-of-staff setup. I started with this repo and have expanded extensively. Here, I’ll focus on the set of skills that cover the core of EM operational work.

    1. Routing: get the tedious stuff off your desk

    Tedious but useful: maintaining a source of truth, and making sure that incoming requests get appropriately routed. Many EMs try, reasonably, to enforce a process here, but let’s be real; that process never applies to the C*O or your boss. They send the request as and how it works for them.

    I had a Zap set up for this, but it relied on a narrow trigger. Now, I have a skill that scans the channels where work comes in and reconciles them against the boards where work is supposed to live. It is also instructed to read the thread before flagging anything. If the ask is resolved in the replies (“we already have this”), flagging it anyway just makes noise, which is the thing I’m trying to reduce.

    That last rule is important because I don’t want one more thing pinging me. The point of routing isn’t to surface more; it’s to surface usefully and reconcile quickly, so the backlog reflects reality.

    2. Reporting: start the day knowing what’s going on

    The reports run first thing, and they run ops-first. Strict ordering: anything broken right now beats anything in flight, which beats anything in the backlog, which beats anything in the future. The daily version is deliberately short; a few lines, only the highest-signal items, and if nothing flags it just says “clear.” I don’t want a dashboard I have to interpret; I want one line that tells me whether my initial plan for the day has to go in the bin.

    At longer cadence: a weekly view for what’s moving and what’s stuck, a monthly one for the board update. Same sources, different altitude. Daily keeps me from missing fires; weekly keeps me from missing drift; monthly is a quick and useful way to keep other people in the loop.

    “I have a morning report” is the most boring possible sentence. But I think of it not as a report, but as an orientation to my day; something that looks through everything in a structured way, so that I know where I am and where I need to go, quickly. The terminal is also the feature: plain text on a yellow background (so I can distinguish that terminal from all the others), and I don’t risk getting distracted by “just this one small thing”, which is a) never just the one, and b) rarely that small.

    At a previous job, once I stopped getting pinged on every incident, I stopped knowing they were happening as they were happening; I learned about it when I reached that particular channel in Mattermost, or got through all the explicit demands for my attention in Asana. On some level, that’s fine and expected: if, as a director+, you’re in every incident, that is itself the problem, and incident response being able to run to your standards without you being aware is evidence that it has resolved.

    But then I had to look at everything. Now I can have structured, prioritized information without needing to. Cheap operational awareness is a win.

    3. Understanding: what’s actually going on, versus what we agreed

    Once you’re organized, and oriented, you come to the actual work of an EM: making the team better.

    It had been a long time since I consistently looked at PRs, but now it’s ~daily. I have heard that PRs are redundant now, and maybe I’ll come around to that point of view, but currently I see a PR as a queryable unit of work. It’s never been easier to know:

    • Is this code good? Dispatch a review agent.
    • Does this architecture make sense? Ask questions or for an architecture document.
    • Does this conform to our standards of ways and working? Encode those in claude.md and check.
    • Are the docs up to date? Ask, and then update.

    Better understanding of the work used to convert into process changes; tweak the review policy, change how we run standups. That work is still important, more so than ever. But also think about claude.md or equivalent. Did I learn something about how we work more effectively? Propose a change to it. The file is a really useful lever for team effectiveness and consistency.

    The bonus: the skills are alive

    I’m not sharing these skills publicly because I think the skill.md, tailored to my work situations, is much less useful than the way of thinking. But here’s a snippet I think you should take. All my skills have it, and it ensures they keep evolving as I do, and as the work does.

    ## Living document
    Update this skill when:
    - Triage patterns emerge from real audits
    - A new source of truth comes online
    - The way the work actually happens shifts

    Coming back to the start – I used to manage a lot of people, and now I use AI to manage (and do!) a lot of work and far fewer people. The thing I loved, and still love, about managing people is that they would learn and grow. Skills doing that is not as rewarding – but it is necessary to function.

  • The New Realities of EM Lyfe

    Image credit: Joe Groove

    A fascinating thing is happening. EMs are saying it’s better to be an IC. ICs think being an EM is where it’s at.

    This is part of the AI shift. The industry seems to be in chaos, and wherever you are, somewhere else seems better. But below that, it’s not just the job that’s changing. It’s the context we’re operating in hitting like a bucket of cold water.

    The seller’s market is over

    We lived in a seller’s market, and we thought it was because of our own brilliance. Jobs were easy to come by, and with them comp, job titles and perks.

    It’s a buyer’s market now and that loss of leverage means we have to justify our impact. If you think you can get a better job, the organization is more likely to say “okay” than give a meaningful counteroffer. It’s always been true you shouldn’t negotiate on a job you don’t mean to take, but now that needs to be a hard line as you’re more likely than ever to be called on it.

    It’s a hard thing to accept, being less special and less in demand.

    The attrition is the point

    When management is an abstraction over people, it only has value when people do.

    For example, during ZIRP, being a good hiring manager was a huge part of the job, and a good hiring process was a real differentiator. People were the constraint. Companies competed on how well they identified, attracted and developed talent, because that was what determined what you could build.

    That’s gone. Hiring is slow or frozen. The L&D budget has been slashed. I wrote last year that management debt was looking cheap. Now I would say it’s looking actively desired.

    Why develop your people if attrition will sort it out for you. Why give hard feedback if the person will burn out and leave. Why fix morale if the ones with options have already gone and the ones who stayed can’t go anywhere. The workforce that’s left is cheaper, quieter, and more grateful.

    The risk, of course, is that the people without options aren’t usually the people you most wanted to keep. This is the AI-era debt; we’ll see what it costs down the line.

    Mass layoffs are the new RTO

    Post-pandemic, return to office looked easier than management fundamentals. Remote work didn’t break those organizations. It made it visible long term deficiencies that were too expensive and structural to fix.

    Mass layoffs are the new blunt instrument.

    Running a layoff is, bureaucratically, easier than writing a PIP. A PIP requires you have been managing the person. Documentation, expectations, feedback they had a chance to act on. A layoff requires a spreadsheet and a comms plan.

    Both punish everyone for problems leadership created. I miss the time when a layoff included an admission of failure. Now they read more like an acceptance speech for visionary of the year.

    This is not to say I don’t think AI will restructure the workforce. I do. I’ve been realizing efficiency gains with it. Reflecting on my time running a large org, I don’t honestly know how I’d make those gains real without a layoff. But that’s not an indictment of the workforce, nor one that I would measure in a %. It’s the change-management and people-development bill coming due. What was less than optimal becomes a structural block.

    We never agreed what an EM is

    We never had a shared definition of what an engineering manager is. Sometimes you could figure it out from the job description, but not always. People-leader, technical-leader, project-runner, career-developer, information-router, scope-holder, vibe-shaper. The profile depended on the values of leadership and the outcome of the latest reorg.

    Fundamentally, you didn’t have to be great at all the things to be good enough for the org, and the people stuff was big enough and fuzzy enough that it often became the job.

    Now I keep seeing the phrase “player coach” and I don’t know what it means. But the overall shift is, I think, pretty clear: get closer to the work, drive delivery improvements, be able not just to know what is going on but consistently make it better (or at least faster).

    Without a good definition, it’s much harder to absorb the chaos of senior leadership litigating in public whether the role should even exist. Trying to “improve productivity” by “doing the work” has ICs describing the output as AI slop. Being told you could be more efficient by having fewer 1:1s, but no one gave that memo to the ICs who still expect their 30+ minutes a week as well as an actual fix for the things they’re complaining about.

    It’s hard to fit all this conflicting feedback into an undefined scope.

    The force multiplier

    A consistent thing I keep seeing from EMs is moral injury. They got into the job because they care about their teams and want to support them, and they feel conflicted between that calling and the organization’s demands.

    It’s fair and understandable. The challenge, I think, is moving to more of a collective care than an individual one. And rightsizing your care to the market we’re in. Taking personal responsibility for things where you have little to no power is a recipe for burnout.

    Something I have long believed: a manager is a multiplier on the team. The worst ones for bad. In a growth market, you didn’t have to be much more than a 1x to have value. Now, the expectations are higher.

    Framing the role this way, a force multiplier for the team, creates clarity. You’re expected to make the team better. It also explains the calculus in a way that makes sense. If being a great hiring manager was a multiplier effect before, now it’s not. Retention is not seen as valuable. I believe retaining your strongest team members still will be, but that’s unlikely to be everyone. You’ll need to pick your battles.

    The thing is, there’s a good chance your organization won’t tell you how to do that. You have to figure out how to take in the information you have, and figure it out for yourself.

    If that sounds like a lot, the EM Survival Guide cohort 2 starts in June. Join us, we’d love to help you.

  • What’s Your Job as an Engineering Manager?

    Image credit: Joe Groove

    As a manager, maybe you start your day looking at your calendar, or the pings that are already piling up. It can be easy to get caught up in what people are asking of you – but your job needs to look beyond the requests and into the causes underlying them.

    Here’s what I think the job of an engineering manager actually is:

    You’re a force multiplier for a team, and you take responsibility for that team.

    There’s a lot to unpack in that. But here I want to talk about three things:

    • The timeframe you live on
    • The distinction between a learning opportunity and a fuckup
    • The Clarify and Shard

    The Three Timeframes

    As an EM, you don’t just live on one time horizon. You need to live on multiple, and that needs to change over time. Consider your week – how much time have you spent on the immediate, versus the longer term.

    This is clearest when you’re ramping up on a new role. Then it roughly looks like:

    This week: What is a problem this week? Get it fixed.

    This month: What is a problem this month? Systematize it. Delegate it.

    Next quarter, next year: What is a problem next quarter or year? Make a plan.

    It’s less clear when you’re in the middle of things. Of course you go back and forth. Of course you pitch in when someone’s sick or there’s an incident. A week when you don’t get to the future is okay. Every week is not. A problem you don’t fully root cause is not the end of the world. But some of them are probably connected, and you’ll never get to those connections if you don’t get to stop and think.

    The pull of the urgent is strong, and bluntly handling the urgent makes your immediate value clearer. Your real value, though, that shows up over time.

    Learning Opportunities vs. Fuckups

    As an EM you need to both develop your team, and hold them accountable. When faced with a person + challenge, you need to understand: what’s a learning opportunity and what’s a fuckup?

    A learning opportunity is when your teammate missed something. They didn’t know, they didn’t see it, with the best of intentions they made a call that turned out wrong.

    A fuckup is when the risk was called – by you or someone else – and they did it anyway.

    Your job as a force multiplier is to increase learning opportunities and reduce fuckups. Learning opportunities are how people grow – they’re the place for the blameless postmortem, the non-judgemental deconstruction, and the process update.

    Fuckups are unforced errors that erode trust. They are where you need to be clear on accountability, what’s negotiable – and what is not. Was the process ignored? Was something not clear?

    When you’re coaching someone through these situations, say what you believe. Ask the question about what you’re curious about.

    Delivery overshot by a week? Learning opportunity. A quarter? That’s a fuckup. And it shouldn’t happen again.

    New manager didn’t realize the hire needed specific feedback? Learning opportunity. You told them and they didn’t do it? Fuckup.

    Incident from factors no one saw coming? Learning opportunity. Same incident twice because the process wasn’t followed? Fuckup.

    The learning opportunity, you can get curious about what can be learned from it.

    The fuckup? The question is more direct – how did this happen, and why am I finding this out now?

    Clarify and Shard

    One of the ways to create learning opportunities is what I call the “clarify and shard”. It’s a leader’s job to navigate ambiguity, and create clarity for their team.

    In the ambiguity, you make the ~~vibes~~ concrete. That feeling that the thing is slow, or the initiative is not working, or the process is wrong – you go into it and you come out with a point of view.

    That clarity can then be sharded (delegated, not necessarily just to one person). It’s the learning opportunity – with some guard rails that prevent it becoming a fuckup.

    What does this look like in practice?

    For example: the vibes say you’re no longer confident in the hiring process – that’s the ambiguity. Making it concrete looks like figuring out why that is. What parts of it aren’t working, or aren’t giving signal. Once the outcomes needed are clear, you can delegate.

    Another: the vibes say DevEx is slowing the team down. Getting concrete is about digging into what is slower and why, and whether or not that’s a problem. Maybe the change is that you have a PM now and they want to spec things? That’s good. But if they are becoming a bottleneck – that’s not. Now you know what you need to fix.

    Bringing it Together

    Put these together:

    • This week’s problem, fix it – then figure out if it’s a learning opportunity or a fuckup.
    • This month’s problem, run the clarify and shard.
    • Next quarter or year – make space for the ambiguity. You have some thinking to do.

    So when you look at your calendar tomorrow, or that pile of pings – remember you’re not just responding to requests. You’re looking for patterns, building systems, and clearing the path ahead. That’s what makes you a force multiplier.

    The hardest part? You won’t see the impact of the third timeframe for months. Your calendar will keep filling up with the urgent. But your job is to protect that thinking time anyway – because that’s where your real value as a leader shows up.


    If this was helpful, you might also like The Engineering Manager Survival Guide. An 8 week fully async course, to help you survive – and thrive – as an EM in the post-ZIRP era. Start March 13th. Early bird ends Feb 28th.

  • Announcing: The Engineering Manager Survival Guide

    Image credit: Joe Groove

    One of the biggest issues I saw running remote teams for the past decade+ was the lack of good engineering manager training. With a global team it’s harder (and more expensive) to get everyone in the same place at one time. With a small team, the cost of doing anything custom is infeasible.

    To help new managers I was responsible for be successful, I had a set of options. We’d attend LeadDev as a group – but that happens once or twice a year and not everyone could make it. Many people would take Co-Active Fundamentals training, which is great – but general. I had a roster of coaches I recommended for 1:1, but that budget wasn’t always available.

    In the post-ZIRP era, being an engineering manager is harder than ever. When headcount was a vanity metric, managers had value simply as an abstraction layer over a number of people. When things were growing fast, there were opportunities to move up just because someone needed to fill the position.

    That era is over.

    Now it feels more important than ever to have a clear point of view on how an engineering manager actually creates impact – and how to support yourself while doing it.

    What is the EM Survival Guide?

    Jean Hsu and I designed The Engineering Manager Survival Guide for managers navigating this new reality. Whether you’re a new manager trying to ramp up, or a more experienced one who knows you’d benefit from devoting some time to consider your approach, this course gives you the frameworks and tools to be effective without burning out.

    The course runs over 8 weeks with 4 modules. Each module includes:

    • Written content and frameworks
    • Audio conversations between Jean and me, with personal stories and reflections
    • Exercises to apply what you’ve learned to your specific situation
    • Personal feedback from us on your submissions

    It’s designed to fit into a busy schedule while still creating space for real reflection and change. Around 60-90 minutes a week, in pieces, as you can fit them in.

    Why now?

    The expectations for engineering managers have fundamentally shifted. The role used to be about coordination and headcount. Now it’s about tangible impact, strategy, and doing more with less.

    If you’re feeling squashed between what your team wants from you and what your boss expects, if you’re wondering how to be effective without burning out, if you want to feel intentional instead of reactive – this course is for you.

    It can be hard to make time to step back and learn. We get it, and we’ve designed this course to fit your schedule. Plan to spend a minimum of 60-90 minutes a week, and it’s completely asynchronous, so you can listen to our audio conversations on a walk or in the car, read the module content in between meetings, and do each module’s targeted exercises whenever is best for you.


    Enrollment is open now.

    Early bird pricing: $799 USD (available until February 28th)

    Regular pricing: $899 USD

    The course starts March 13th, 2026. Enrollment closes March 10th or when we are at capacity.

    👉 Learn more

  • Decisions

    Credit: Joe Groove

    Recently, someone asked me for my “Leadership philosophy”. My initial reaction was to panic, but after taking a deep breath and a bit of time to think, I came up with this answer:

    “My job is to make it easier for people to make good decisions.”

    What does that mean?

    Firstly – that my job is not to make decisions. Sometimes (often!) it is, but it’s important to think about when someone else should be able to make the decision and how to change it for next time.

    What do people need to make decisions?

    • Context: What is the information around the decision they need to understand? As you rise up the org chart, you end up with a broad amount of context,so think about what you need to be distilling and passing on.
    • Scope / Responsibility: This is clarity about the scope of the decisions people can make, and what they are responsible for.
    • Timeframe: What timeframe is being optimized for.

    Local / focused decisions can help teams move faster in the short term, but have higher costs over time – e.g. optimizing for features over infrastructure that would make more features easy. Shifting this requires:

    • Enough shared context such that people can identify possible overlap.
    • Clarity about how and when a broader scope can make sense.
    • Understanding of where it’s critical to just deliver vs where it’s possible to justify longer investments (i.e product market fit vs iteration).