Landing the plane

Leave a comment
Growth

Everyone loves the start of a project. There’s the kickoff, the fresh energy of newness, and the blank canvas of a new feature to build. There’s a particular optimism that comes with beginnings, when the team is aligned, the scope feels manageable, and the possibilities stretch out ahead of you. Starting is the fun part, which is probably why so many of us have a pile of musical instruments and unfinished side projects.

But the end is a different story. The final 10% of a project, where the work gets fiddly, the energy dips, and the finish line keeps moving, is where most projects quietly fall apart.

If starting a project is like takeoff, finishing it is like landing, demanding a completely different kind of skill and attention, and it’s where most of the risk accrues. After all, the hardest part of flying a plane is landing it.

This article is about why endings are so hard, what goes wrong when you don’t manage them deliberately, and how to land your projects well. Here’s what we’re going to cover:

  • Why the final stretch of a project is psychologically and structurally harder than the beginning.
  • The anti-patterns that cause projects to die quietly instead of finishing cleanly.
  • Why scope creep accelerates at the worst possible moment, and how to protect against it.
  • A practical playbook for landing well.

If you find this topic interesting, here are some complementary articles from the archive:

  • One bottleneck at a time argues that when everything feels urgent, the counterintuitive move is to focus on the single thing that’s actually blocking progress, which is also the discipline the final stretch demands.
  • The beauty of constraints makes the case that saying “not now” to good ideas is a skill rather than a compromise, and one that pays off most when scope pressure is highest.
  • One list to rule them all is about the power of a single prioritised backlog, which becomes essential when you’re deciding what makes the cut and what doesn’t.
  • Invert, always invert walks through the habit of asking “how could this go wrong?” before it does, a question worth asking explicitly as any project approaches the finish line.

So, let’s dig in.

Why the end is the hardest part

So why does the final stretch of a project feel so different from the beginning? Part of it is structural, since the work that remains is often the hardest of the whole project: getting it out there to customers. But a surprising amount of the difficulty is psychological, and understanding the psychology helps you manage it.

There’s a well-known adage in programming, the ninety-ninety rule, credited to Tom Cargill of Bell Labs: the first 90% of the work takes 90% of the time, and the remaining 10% takes the other 90%. Jeff Atwood wrote about living in that state in his classic post on being perpetually 90% done. I’m sure you can associate with this.

That’s because the last 10% is where you hit the edge cases, the integration problems, and the thousand small decisions that weren’t apparent when the architecture was being sketched on a whiteboard, or the initial lines of code were being written.

This certainly feels familiar to me, so I’m sure it feels familiar to you too.

The psychological side is just as powerful. Novelty is easier to desire than completion, because starting something new promises reward! And possibility! Finishing, by contrast, is structural and unglamorous, and there’s none of that novel pull in writing migration scripts or fixing the remaining glut of accessibility bugs.

Seth Godin calls this the Dip in his book of the same name: that long, unrewarding stretch between the initial excitement and the satisfaction of completion. Most people quit in the Dip not because the work is impossible, but because the emotional fuel runs out. I’m glad you can’t see my private GitHub projects.

Then there’s the planning fallacy, coined by Kahneman and Tversky and popularised in Thinking, Fast and Slow: we systematically underestimate how long tasks will take, especially tasks we haven’t done before. This then hits hardest at the end of projects, because the remaining work is precisely the kind that’s challenging to estimate (“what iterations will customers need to make this great?”)

Additionally, integrations, testing, deployment, and documentation are the tasks that expand to fill whatever time you thought you had, and then some…

Research by Diwas KC, Bradley Staats, Maryam Kouchaki and Francesca Gino found that when workload rises, people gravitate towards easier tasks to maintain a sense of progress. This is completion bias, and it maps directly to the final stretch: when pressure builds, your team will instinctively reach for minor UI tweaks and documentation fixes rather than tackling the hardest parts of the work that stand between them and shipping.

You might expect the “goal gradient” effect to help here. Research by Kivetz, Urminsky, and Zheng shows that effort naturally accelerates as you approach a goal. But, however, the goal gradient only works when the finish line is visible and stable. In software, the finish line keeps moving and moving, and that’s the problem!

The quiet death

Let’s invert the question to garner more insight. Instead of asking what a good ending looks like, consider what happens when a project never officially ends at all.

You’ll have all experienced the project that was “almost done” three months ago, where the team mentally moved on but nobody formally closed the book. Telltale signs: the Linear board still has tickets in it, nobody’s looked at them in weeks, and there was no retrospective, no celebration, no learning captured, and rather than failing spectacularly, it just faded away into the oubliette.

This is the quiet death, and it’s far more common than outright failure. Think about the project your team spent months on that got to about 90% before, say, a reorg shifted priorities and you didn’t touch it again.

Nobody makes an explicit decision to stop a project, after all: people get absorbed into other work, the remaining tickets sit untouched, and a few months later someone quietly archives the board. All that effort, all those decisions and trade-offs, and nothing shipped, and the worst part is that often nobody even notices!

The reason quiet deaths are so insidious is that “95% done” is the most expensive state a project can be in: you’ve made the maximum investment but delivered zero value.

Or worse, something partially shipped, enough to create maintenance burden but not enough to deliver the promised outcome.

The organisational cost compounds over time. When projects routinely fade instead of finishing, trust erodes between engineers and leadership. The next time you kick off something ambitious, your team starts with scepticism rather than excitement.

Interestingly, the Zeigarnik effect describes how unfinished tasks occupy mental bandwidth: your brain keeps returning to incomplete work, creating a low-grade cognitive load, which gives yet another reason to finish stuff: it helps you concentrate better on the next thing.

What makes the lack of landing projects worse is that when “almost done” drags on long enough, the tension for getting it done dissipates. The project becomes background noise, neither finished nor actively worked on, consuming mental space without the urgency that might push it across the line.

The one more thing trap

If the quiet death is what happens when nobody’s paying attention, the “one more thing” trap is what happens when everyone starts paying attention at exactly the wrong moment.

For months, stakeholders were vaguely aware your team was building something. They attended the occasional update meeting, nodded along, and went back to their own priorities. But now the project is visible, there’s a working demo, and suddenly everyone has opinions.

“Can we add dark mode before launch?” “What about accessibility for the new flow?” “I just saw what the competitor shipped last week, could we match that?” Each request sounds reasonable in isolation, each one is small, and each one pushes the finish line a little further away.

Jon Acuff, in his book Finish, calls these “noble obstacles”: things that look like smart preparation, feel responsible, yet masquerade as doing things right.

And it isn’t just stakeholders who give us these requirements; we do it too! “We should refactor this module before we ship” is a noble obstacle, and “let’s speed this endpoint up a little more so the P95 is green” is another.

They’re hard to argue against because they sound good, and that’s precisely what makes them dangerous.

In this phase, protecting scope becomes your primary job as a leader. This is where the beauty of constraints applies most directly: the discipline to say “not now” to genuinely good ideas is what separates projects that ship from projects that expand forever.

Joel Spolsky put it memorably. “A 50%-good solution that people actually have solves more problems and survives longer than a 99% solution that nobody has because it’s in your lab, where you’re endlessly polishing the damn thing.”

The distinction between “done” and “done enough” is one of the most important judgements an engineer makes, and it’s one you’ll need to make repeatedly in the final stretch. “Done enough” means shipping, not settling.

Memories of shipping

So far, we’ve covered why endings are hard and what goes wrong. How a project ends does more than close out the deliverable, because it sets how your team feels about the next hard thing.

Daniel Kahneman’s research on the peak-end rule shows that people judge experiences primarily by two moments: the peak (the most intense point) and the end. “Duration neglect” means that how long something took matters far less than you’d expect, since you only remember those previous two parts.

A six-month project that ends in chaos will be remembered negatively, regardless of how smooth the middle was, while one that ends cleanly, with celebration and reflection, will be remembered positively.

This has direct implications for your team. The way a project ends shapes how they feel about taking on the next hard thing. If their last experience ended with a death march, ever-expanding scope and no acknowledgement, they’ll approach the next project with dread, but if it ended with a clean landing and recognition of their effort, they’ll approach it with confidence.

For senior leaders, the argument is strategic. How your projects end feeds directly into retention, morale, and how ambitious your team is willing to be. This is about building an organisational culture where finishing is valued, expected, and celebrated. How do you celebrate things shipping?

Teams that keep experiencing bad endings will stop putting their hands up for the most challenging future projects, and you end up paying that debt forever.

Landing well

So what does it look like to land a project well? The leader’s role in the final stretch is fundamentally different from the rest of the project, and recognising that shift is the first step.

During the middle of a project, your job is often to create space: remove blockers, shield the team from distractions, and get in the details and execute.

During the final stretch, your role shifts towards tighter involvement. The approach phase calls for more active steering, more frequent check-ins, and more aggressive prioritisation, and none of that is the same thing as micromanagement.

Here’s what it looks like in practice to end well:

  • Increase your cadence. If you were doing weekly check-ins, move to twice a week or daily, because the final stretch moves faster, surprises arrive more frequently, and you need to be close enough to the work to spot problems before they compound.
  • Protect scope ruthlessly. Every new request gets the same answer: “That’s a great idea for v2.” Maintain a single, prioritised list of what’s left (as described in One list to rule them all), and resist the temptation to add to it. Your team needs to see the finish line getting closer, not further away.
  • Overcommunicate with stakeholders. In the final stretch, stakeholders need more updates, not fewer. Silence breeds anxiety, and anxious stakeholders show up with last-minute requests, so a brief daily update (”here’s where we are, here’s what’s left, here’s when we expect to ship”) is cheap insurance against scope creep.
  • Favour systems over heroics. A late-night push might feel like the only option, but it’s almost always a sign that something went wrong or was forgotten about upstream. Build a checklist for the final stretch (what needs to happen before shipping, in what order, and who owns each item) to bring structure. Checklists aren’t glamorous, but they are far more reliable than adrenaline.
  • Shield the team from new requests. You are the buffer between your team and the rest of the organisation. Every “quick question” and “small ask” that reaches your team in the final days is a potential derailment, so take those hits yourself. When a late requirement genuinely is non-negotiable, don’t just absorb it: trade something else out. “We can add this, but something else has to come out. Which is it?” is a more honest conversation than pretending the timeline can absorb everything.

Once you’ve shipped, the work isn’t done, because how you close the project matters as much as how you land it:

  • Run a proper retrospective. Not a perfunctory one where everyone says “communication could have been better,” but a genuine reflection on what worked, what didn’t, and what you’d do differently. The insights from a project ending are some of the most valuable you’ll capture, precisely because the details are still fresh.
  • Celebrate the landing. The act of marking the ending matters more than the scale of the celebration. A written retrospective that opens with what went well, individual messages naming specific contributions, or time in your next team meeting to acknowledge that the hard part is done will all do the job.
  • Plan for the energy dip. Your team’s energy peaked just before shipping, so after the launch there’s a natural drop, and if you immediately pile on the next big initiative, you’ll burn people out. Give your team a beat to tackle smaller items, pay down technical debt, or simply catch their breath.

Your turn

Here are three things you can try this week:

  • Audit your current projects. Look at everything your team is working on and ask: is anything stuck at “almost done”? If a project has been at 90% for more than a couple of weeks, it needs active intervention, either a push to finish or a deliberate decision to stop. The quiet death is always more expensive than a conscious call to shelve something.
  • Write a pre-mortem for your next launch. Before your current project enters its final stretch, gather your team and ask: “How could this ending go badly?” You’ll surface risks you hadn’t considered, and you can build your landing checklist around mitigating them. This is inversion applied to project endings.
  • Create a landing checklist. Build a reusable checklist for the final stretch of any project: scope freeze date, stakeholder communication cadence, shipping criteria, retrospective date, and celebration plan. Having this template ready means you won’t be designing your approach during the most pressured phase of the project.

Wrapping up

Starting a project is exciting, and it should be, but the start is the easy part. The end is where value is delivered, where your team’s experience of the project is cemented, and where trust with stakeholders is either built or broken.

Landing well isn’t complicated, though it does take tighter involvement, disciplined scope protection, clear communication, and the simple act of marking the ending when it comes, all things within your control.

So the next time you’re planning a project, don’t just plan the takeoff, plan the landing too. It’s genuinely the hardest part.

Until next time.

Code Yellow, Code Red

Leave a comment
Growth

Towards the end of 2025, it seemed that we couldn’t get through a week at Provet without some kind of infrastructure degradation. Outages were piling up, they were hard to diagnose, and customers were losing patience.

When a major AWS outage hit in October, our customers didn’t distinguish between Amazon’s problem and ours: months of flakiness had already eroded their trust.

So we declared a Code Yellow, the first time we’d done it: a company-wide written announcement explaining the concept, the structure, the exit criteria, and the reasoning. The target was simple: tighten our SLAs and achieve zero downtime for eight consecutive weeks.

The good news was that we hit it, with only one brief degradation incident in the entire period, and the contrast with where we’d been just weeks earlier was extraordinary.

This article is about that experience, and about the broader practice of Code Yellows and Code Reds: what they are, how to run one well, when to call one, and when to end one.

Here’s what we’re going to cover:

  • What Code Yellow and Code Red actually mean, and where the terms come from.
  • How we ran ours at Provet: the structure, the work, and what we learned.
  • A generalised template you can adapt for your own organisation.
  • When to call one, when to escalate, and the failure modes to watch for.

If you find this topic interesting, here are some complementary articles from the archive:

  • One bottleneck at a time explores why fixing one binding constraint compounds faster than optimising everything at once, which is what a Code Yellow forces you to do.
  • The beauty of constraints covers how deliberate limitation unlocks unconventional thinking.
  • Going direct is about communicating without intermediaries, which becomes essential during an escalation.
  • Invert, always invert explores defining failure first, which connects directly to setting exit criteria before you begin.

Let’s get going.

What Code Yellow and Code Red actually mean

Before I share our experience, it’s worth defining the vocabulary.

The terms Code Yellow and Code Red originated at Google. As Steven Levy describes in In The Plex, the name came from a yellow tank top owned by engineering director Wayne Rosing: whoever wore the shirt became the designated leader and could tap anyone at Google on the shoulder, pulling them off their current project to help.

The practice has since spread across the industry: LinkedIn, Meta, Shopify, Instacart, and OpenAI all use variations of it. And us of course, and maybe even you too.

The core idea is simple. A Code Yellow is a formal declaration that something is seriously wrong and needs concentrated, cross-functional attention now, before it becomes catastrophic, while a Code Red is the next level up: an existential threat that demands everything stops until it is fixed.

Here’s the distinction:

DimensionCode YellowCode Red
SeveritySerious but not existentialExistential threat or critical failure
UrgencyPreventative interventionEmergency response
DurationWeeks to monthsDays to weeks
Work hoursPrimary focus during business hoursAll hands, around the clock
Normal workDeprioritised but not fully stoppedFully paused

The real power lies in having a shared language at the company, not in the table’s definitions. When everyone in your organisation understands what “Code Yellow” means, you don’t need to explain the severity, negotiate priority, or convince people to shift their focus, because the concept itself does the work for you.

Compare that to “we’re really concerned about uptime” or “this needs to be a top priority,” both of which are vague enough to be ignored, or for other functions like product to argue that their own priorities are more important.

As LinkedIn’s SRE team described it, the goal is to get a team “out of a reactive mode where they are running from crisis to crisis and into a proactive state.” That’s precisely what it felt like for us, and what the next section is about.

How we ran ours

Let me dig into the Provet Code Yellow in more detail.

The trigger was a pattern, not a single incident. As described in the opening of this article, throughout the back end of 2025, we’d had multiple outages that were frustratingly difficult to diagnose, and that difficulty itself was a signal: it pointed to deeper infrastructure problems rather than isolated bugs.

When the October AWS outage hit, our customers perceived it as our problem because months of instability had already conditioned them to expect that this again was all our fault.

As an exec team, we agreed that something bolder was needed, and the CEO signed off. I announced the initiative to the entire company in writing, and since it was our first Code Yellow, the announcement explained the concept itself alongside the specifics: what we were targeting, how long it would take, what the exit criteria were, and why we were doing it now.

The framing was deliberate. Uptime metrics are getting worse, we are losing trust with customers, and we need to act now before this becomes a Code Red.

The first week was intense and, honestly, chaotic: daily stand-ups, daily war rooms, and a full audit of monitoring, speed measurements, logs, and alerting.

The scope of what needed fixing was larger than anyone had anticipated, and prioritising within the Code Yellow itself generated real debate, though we found a surprising amount of low-hanging fruit (e.g. implementing additional timeouts and circuit breakers) and those quick wins built early momentum.

As the immediate fixes gave way to longer-term infrastructure work (migrating services to better technologies, rearchitecting for resilience), the cadence naturally slowed from daily to bi-weekly, then weekly.

Our approach was to walk the software stack from the bottom up: starting at the databases and what was connected to them, analysing access patterns and API calls, then moving further up the stack to look at rate limiting. Who was calling our API? What slow queries existed? What should the timeouts be across the stack as a result?

We also walked the stack from the outside in, looking at monitoring and alerting and identifying gaps that needed fixing.

Throughout, we maintained async updates in a public Slack channel called #code-yellow-uptime, deliberately over-sharing so anyone in the company could see exactly what was happening. Written shares followed a similar cadence to the above.

That transparency, the proximity and visibility it created to the actual work, was one of the most valuable parts of the whole exercise.

One powerful structural decision of Code Yellows is what is called “tap on the shoulder” authority. If an endpoint was particularly slow for our biggest customers, anyone working on the Code Yellow could tap the domain team that owned it and tell them to reprioritise to speed it up immediately. That kind of authority only works when the entire company understands and supports the escalation, which is why the concept and upfront communication mattered so much.

Getting people to deprioritise their roadmap work was surprisingly easy in our case, though I recognise that’s partly a function of context. At a company of our size, the instability was felt by everyone, and after the AWS outage, everyone saw fixing it as the number one priority. After all, a direct correlation exists between the stability of our product and the happiness of our customers.

I suspect deprioritisation is harder at larger organisations where the pain isn’t evenly distributed. If that’s your world, the communication piece becomes even more critical: the problem statement needs to make the impact concrete and company-wide, and getting exec buy-in and sign off is critical.

If you’re a manager without the authority to deprioritise on your own, bring the data to your leadership and let them make the call publicly. The worst outcome is a quiet, unofficial Code Yellow where your team bears the cost without organisational support.

To give you a sense of the breadth, we improved and tightened rate limiting, fixed database timeouts, added circuit breakers, migrated away from Redis in areas where it was a bottleneck, and found and fixed memory leaks in background tasks. We added measurement of all of our API calls, partitioned by team, and set minimum speed thresholds that teams had to meet, lowering that threshold as the weeks went on.

We migrated our incident management tooling to incident.io and retrained everybody on a tighter incident process. And that’s just the tip of the iceberg.

When we hit our target, eight weeks with effectively 100% uptime as measured by our monitoring, it felt awesome. The communications rolled out in stages: engineering first, then company-wide, then a customer-facing announcement that was deliberately non-technical.

If I were to do it again, I’d push even harder in the first two to three weeks, because that initial burst was where the bulk of the work happened and increasing the intensity early, when momentum is high, would have compounded the gains faster.

The template: how to run your own

So how do you take something like our experience and generalise it? Whether you’re dealing with reliability problems, scaling challenges, or technical debt that’s reached crisis levels, the underlying framework is the same.

You need four components before you start your own Code Yellow:

  • Problem statement. This needs to be simple enough that everyone in the organisation can repeat it. “Our infrastructure is unreliable and customers are losing trust” is clear. “We need to improve our SLA posture across the P0 service tier” is not.
  • Exit criteria. These need to be specific, measurable, and time-bound, and you should define them before you enter the Code Yellow (ours was eight weeks of zero downtime). Without clear exit criteria, you’ll never know when you’re done, and the Code Yellow will either drag on forever or fizzle out.
  • Timeframe. Set a clear start date and expected end date, and don’t plan for longer than a quarter: if your Code Yellow needs more than three months, you’ve either scoped it too broadly or you’re dealing with a Code Red.
  • Authority structure. You need to define who can pull people in, who reports progress and to whom, and who decides if the scope needs to change. In smaller organisations, this might mean direct “tap on the shoulder” authority, while in larger ones, it might mean escalation through a VP chain or a designated incident commander with cross-team authority. The mechanism matters less than having one that’s explicit and understood.

Communication is the next piece, and it’s worth working hard on getting right: announce the Code Yellow to the full organisation with the problem statement, exit criteria, and timeline, so that surrounding teams know what’s happening, can expect delays on other work, and are ready to help if asked.

Transparency is what gives the Code Yellow its power. There’s nothing optional about it. This is a #announcements channel level communication. A Code Yellow that’s invisible to the rest of the company is just a stressed team working harder, which is exactly the opposite of what a Code Yellow should do; it should rally everyone around the team instead.

There are also cultural prerequisites that matter more than any process. Don’t think of declaring a Code Yellow as an admission of failure. It’s a sign that the organisation is mature enough to recognise a problem early and respond decisively. If early escalation gets punished rather than celebrated, people will avoid it, and by the time someone finally raises the alarm, you’ll be in Code Red territory.

When to call one, when to end one

So you have the vocabulary and the template, but the hardest part isn’t running a Code Yellow: it’s knowing when to start one and, harder still, when to stop.

Common triggers include alert fatigue overwhelming your teams, technical debt reaching crisis levels, key metrics degrading consistently, and incidents piling up faster than you can resolve them. The pattern to look for is a slow boil: as LinkedIn’s SRE team noted, Code Yellows typically result from “increasing technical debt, many small issues or breakdowns in a process” rather than a single dramatic failure.

If you’re waiting for the dramatic failure, you’ve already waited too long.

Escalation to Code Red should happen when something threatens the core business: severe and widening customer impact, existential competitive threats, or fundamental system failures. Google famously declared a Code Red when ChatGPT launched in December 2022, reassigning teams across the company to develop their AI capabilities, which became Gemini. That’s the severity level we’re talking about: existential, not merely inconvenient.

Ending a Code Yellow requires discipline, because exit criteria must be met for it to finish: “we’re exhausted” is not a reason to de-escalate, and neither is “things seem better.” You defined measurable criteria at the start for exactly this reason.

Once you’ve hit them, conduct a blameless retrospective, communicate the conclusion to the full organisation, restart paused work deliberately, and check in on team wellbeing, because the push took a toll and acknowledging that matters.

Crucially, the retrospective of the Code Yellow should produce systemic changes, not just a summary of what happened. If you ran a Code Yellow but nothing changes about how work is prioritised, how monitoring is maintained, or how early warnings are escalated, you’ve treated the symptom without addressing what caused it.

The goal is to make the next Code Yellow less likely, not just to survive this one. For example, earlier in the article we outlined how we pretty much overhauled resiliency across our entire stack.

Finally, watch for these failure modes:

  • Overuse. If you call Code Yellows too often, the signal loses its value: every escalation becomes background noise, and people stop taking them seriously.
  • Performative escalation. This is when war rooms become theatre, with lots of visible activity and impressive dashboards but no real change in priority or approach: if the work during the Code Yellow is the same as before, you haven’t escalated anything.
  • Failure to de-escalate. A Code Yellow that never ends becomes permanent urgency, which is indistinguishable from normal operations, and if you can’t exit, your criteria were wrong.
  • Shortcut temptation. Adding technical debt to exit a Code Yellow defeats the purpose entirely, because you’ll be back in another one within months, this time with even more debt to dig out of.

Your turn

Here are three things you can do with this:

  • Draft your own escalation protocol. Even if you don’t need a Code Yellow right now, having the framework ready means you won’t be designing it during a crisis. Define what triggers a yellow vs. a red in your organisation, who has authority to declare one, and what the communication plan looks like.
  • Reflect on your last crisis. Think about the most recent time your team dropped everything to fix a problem, and ask yourself whether it had a clear problem statement, exit criteria, and a defined timeline. What would have been different if it had been formalised as a Code Yellow?
  • Have the vocabulary conversation. Introduce the concept to your team or your leadership group, because the value of Code Yellow and Code Red as terms is that they compress a lot of meaning into two words. Even if you never formally use them, having a shared understanding of escalation levels makes the next crisis easier to navigate.

Wrapping up

Code Yellows work when they’re structured, have clear exit criteria, and give teams both the autonomy and the permission to focus. They’re a blunt instrument. As one engineering leader at Instacart put it, “Code yellows suck, drain team morale, and they leave a lingering distaste amongst all those involved. Yet they were the most effective and consistent weapon in ensuring we made meaningful progress on our hairiest problems.”

That matches my experience. Running our Code Yellow at Provet was exhausting, but the outcome (real confidence in our infrastructure after months of anxiety) was worth every minute of it. The key is treating them as the exception that proves the rule: a structured, temporary departure from normal operations, not a permanent state of crisis.

Until next time.