Sertaç Yıldırım field notes

Home → Leadership

Cancelling a Project: A Decision, Not a Failure

Monday, 10:40, quarterly planning. The line on the screen: “Automatic portfolio rebalancing — 85%.” Someone from product asked: “Wasn’t it 85% in March too?” It was. I stopped the project in that meeting. Seven months, three engineers, 21 person-months. The last nine went to a question we had already answered in March.

Summary
  • A cancellation is a decision, not a failure. The failure is delaying that decision by three months.
  • Kill criteria are written before you start. A number, a date, a threshold and one owner. Criteria written after the excitement is gone are excuses.
  • Sunk cost is not a number, it is a signature. The project you cannot stop is usually the one with your name on it.
  • The people on the project hear it first. The reason, the parts that will live on and everyone’s next task, all in the same conversation.
  • A cancellation ends when the code is deleted. Code and feature flags left behind “in case we come back” are a project with postponed maintenance, not a cancelled one.

From the field: 85% for three months

The project started in November 2025. The idea was solid. The customer picks a target mix (for example 60% stocks, 30% funds, 10% cash). When the portfolio drifts, the system suggests rebalancing orders, and the customer approves them with one tap. Three engineers, a three-month plan. I was the one who pitched it to senior management. I wrote the budget line myself.

In early February we opened a pilot for 500 customers. At the end of the fourth week, on 3 March, the number came in: 15 of the 500 had rebalanced at least once. 3%. Nobody had written down a threshold, but in the meeting everyone said “we expected around 20%”. So did I.

Then I did this. I said “there are no notifications, customers do not notice the drift”, so we added notifications. In April I said “the approval screen is too complex”, so we simplified it. At the end of May, in week 16 of the pilot, the number was 23 people: 4.6%. The 85% in the status report had not moved since March, because every new piece of work also made the remaining work bigger.

DateSignalMy response
November 2025Start, three-month planNo threshold written
3 FebruaryPilot opened to 500 customers
3 MarchWeek 4: 15/500 (3%)“Notifications are missing” → added
AprilUsage not moving“Approval screen is complex” → simplified
End of MayWeek 16: 23/500 (4.6%)Draft for “one more quarter”
8 June“Wasn’t it 85% in March too?”Cancelled

Writing the last column made me feel ashamed. Every row shows the same move: bad news arrives and I add a feature. No row contains the question “should we stop?”

The mistake was mine, and it was simple. In March the data said “no”. I did not look for what the data meant. I looked for the next feature that would save the project. The decision I made on 8 June was a decision I could have made on 3 March.

A project does not fail when it is cancelled. It fails while the cancellation is being delayed.

Why I stopped it late

I did the sunk cost maths in the build or buy post: money already spent does not come back, and the decision is about the future. I knew that. I knew the table too. I still waited three months, because for me the sunk cost was not a number.

There were three things, and none of them was a row in a table:

  • The signature. I had sold the project upwards. Stopping it meant saying “I was wrong”. Each new feature was a way to postpone that sentence by one more month.
  • The “85%” illusion. It is hard to drop something that looks almost done. But 85% was not a measurement. It was an estimate of the remaining work, and it was estimated again every month.
  • Embarrassment in front of the team. Three people had worked for seven months. I thought “I cannot throw their work away”. But the cancellation was not what wasted their work. Keeping them on something I knew would not work, for three more months, was.

I was asking myself the wrong question: “We have put in so much work, are we going to drop it?” The right question was: “If this project did not exist today, would I give these three people to it for the next three months?” If I had asked it in March, the answer was clear. No.

Kill criteria: written while you are still excited

In the technical strategy post I described the no list: saying no to work that has not started. This post is about saying no to work that has already started, and that is much harder. Started work has defenders, it has effort already spent, and it has the feeling of “almost there”.

Kill criteria are the conditions, agreed in advance, under which a project stops. The only thing that makes stopping easier is making that decision before the project starts. On that day everyone is excited and everyone believes it will work. That is exactly why writing “if this happens, we stop” is cheap on that day. Three months later the same sentence is expensive.

Kill criteria template
PROJECT    : automatic portfolio rebalancing
OWNER      : one name (this person decides, not a committee)

SIGNAL     : share of pilot customers who rebalanced at least once
THRESHOLD  : below 10% at the end of pilot week 4 -> STOP
             10% - 20% -> one single change, 4 more weeks, same question
             above 20% -> continue

TIME       : 3 months at most. if at the end of month 3 the
             "remaining work" estimate is over 1.5x the first
             estimate -> same table, same question

IF WE STOP : 1) the people on the project hear it first
             2) surviving parts are listed and handed to an owner
             3) code and flags are deleted within 2 weeks

# this page is written and signed before the project starts.
# if it is changed later, the change is written with its date.

It is clear what this page would have changed for us. On 3 March we got 3%, and the threshold was 10%. The discussion would have been “what does the page say”, not “what should we add”. The decision would still have been hard. But it would have depended on a sentence written three months earlier, not on my enthusiasm.

The threshold does not have to be exactly right. 10% or 15% can be discussed. What matters is that a threshold exists and that it was written before you saw the result. A threshold you set after seeing the result is a threshold set to fit the result.

Who makes the call?

The “owner: one name” line in the template is not decoration. Our project had no owner. It had a committee: product, me and one person from sales. All three of us saw the number. All three of us waited for the other two to say “stop”. A committee finds it easy to start things. It almost never stops them.

Now every project has a named owner for the stop decision on its first page. That person does not have to decide alone. But when the number falls below the threshold, calling the meeting is their job. If they do not call it, everyone can see that.

Kill criteria are written while you are still excited. Criteria written after the excitement is gone are not criteria. They are excuses.

Telling the team

I made a mistake here too, and it is the part I regret most. I announced the decision in quarterly planning, in front of 14 people. One of the three engineers on the project was in that meeting. The other two learned about it half an hour later, from a message in the team channel. One of them first asked: “Did we do something wrong?”

What I did
  • Decision in a large meeting
  • People on the project learn it from a channel
  • Reason: “usage is low”
  • “Next task” unclear for two weeks

What people hear: “Your work did not matter.”

What it should be
  • The three people first, face to face, the same day
  • Saying clearly: “I made this decision late”
  • Which part will live on, by name
  • Everyone’s next two weeks are clear

What people hear: “The question is answered. Here is the next one.”

The next day I had a separate one-on-one with each of the three. My first sentence was: “This project did not stop because of you. It should have stopped in March, and I did not stop it.” Saying clearly whose decision it was did more for psychological safety on the team than any workshop I ran. People watch how their manager handles their own mistake, and they learn from it how to handle theirs.

The second lesson: someone whose next task is unclear hears the cancellation as a decision about them. For two weeks I told a senior engineer “we will see”. In those two weeks they went to two job interviews. They told me later. They stayed, but I had created those two weeks.

Making the work visible

Saying “your work was not wasted” is not enough. Nobody believes it. You have to show what was not wasted. The week after the cancellation, I sat down with the three engineers for an hour. We listed everything the project had produced. The result surprised me too:

What was builtWhat happened to it
Batch order layer (basket orders, ~3,100 lines)Moved; it became the base of the recurring investment plan work
Risk profile and target mix questionnaireHanded to the compliance team; used in the yearly suitability test
“Drift from target” indicatorOpened by 38% of pilot users; added to the portfolio screen as read-only
Pilot data and customer interviews (11 interviews)A one-page note: “customers want advice, not automatic orders”
Rebalancing engine, notifications, approval flow (~11,500 lines)Deleted

The most valuable row had the least code. Pilot customers were not rebalancing, but they were looking at the drift indicator: 190 of the 500 opened it at least once. So the question was right and the answer was wrong. Customers wanted to know “where has my portfolio drifted”. They did not want to leave the order decision to us. We had this finding in March too. I did not read it.

The three engineers presented this list at the team meeting themselves, not me. Work becomes visible when the people who did it tell the story.

Really deleting the code

A cancellation is decided in a meeting, but that meeting changes nothing in the codebase. On the evening of the decision, the project still had 14,600 lines, 3 services, 2 database tables, 1 scheduled job and 11 feature flags. A feature flag is a switch in configuration that turns a code path on or off without a new deploy. 23 pilot customers still had rebalancing settings saved.

We planned the deletion as two weeks of real work, with an owner:

  1. Customers first. A message to the 23 customers with settings, saying what would happen, and then cancelling their pending suggestions. Turning off a live feature is also a release. It is not switched off quietly.
  2. Separate the parts that live on. The batch order layer moved to its own module, with its tests. Move first, then delete. Not the other way round.
  3. Remove the flags one by one. For each of the 11 flags: delete the code path, delete the flag definition, remove it from configuration. Leaving a flag “off” is not removing it.
  4. Decide about the data. The two tables were archived, with a written date to delete them after 90 days. The scheduled job was stopped and its definition deleted.
“We might come back”

On the previous project we cancelled (a new version of price alerts), we left the code in place. Eight months later, during a config clean-up, the flags went back to their default values. The default was “on”. The half-built alert screen was visible in customers’ apps for 40 minutes. If you want to come back, the code is in the git history. It does not need to stay on the main branch.

At the end of the two weeks, 11,500 lines were deleted, 3,100 lines were moved, and 11 of the 11 flags were gone. I care about this number more than about the cancellation decision. The decision is one sentence. The deletion is the proof that the decision was really made.

Code that is not deleted has not been cancelled. Its maintenance has only been postponed.

What to track

WhatWhy
Weeks a status report stays at the same percentageIf it is flat for more than three weeks, the scope is growing, not the progress
The gap between the signal and the written thresholdIf there is no threshold you cannot fill in this row; that is the first alarm
Features added after a bad signalAnswering a bad signal with a new feature is a way of postponing
Live flags and lines of code from cancelled projectsShould be zero; if not, the cancellation is not finished
Person-days with no clear next task after a cancellationThe longer the uncertainty, the more personal the cancellation feels

What did not work for me

  • Answering a bad signal with features. Notifications and a simpler approval screen moved pilot usage from 3% to 4.6%. The right question was not “what did we miss”. It was “do customers want this at all”.
  • “Let’s put it on hold.” My first reflex was to freeze the project instead of cancelling it. A frozen project is nobody’s priority, but it takes up space in everyone’s head. Two days later I used the word “cancelled”.
  • A positive retrospective. In the first retrospective everyone listed what went well. Nobody asked “why didn’t we stop in March?” I should have asked it, because I was the answer.

Checklist

Can you stop a project?
  • Does every running project have written kill criteria — a number, a threshold, a date and an owner?
  • Were those criteria written before anyone saw the results?
  • When did I last ask “if this project did not exist today, would I put this team on it”?
  • How many features did I add after a bad signal?
  • Did the people on the project hear about the cancellation before anyone else?
  • Is everyone’s next task clear within the same week?
  • Are the parts that live on listed by name?
  • Were the code, flags, tables and scheduled jobs really deleted?

Conclusion

In that planning meeting, the person who asked “wasn’t it 85% in March too?” asked the question I had avoided asking myself for three months. I knew the answer. I just did not want to say it out loud.

Stopping the project took three weeks: one decision, three one-on-ones, one list and two weeks of deletion work. Not stopping it took three months and cost 9 person-months. The real cost was not the cancellation. It was the delay.

Today every project has kill criteria on its first page. Most of them are never used. When they are, the discussion is short, because the decision was already made: while we were excited, before we saw the result, by our own hand.