ap.Abhishek Patel

Search

Search notes, essays, projects, and the library. Use arrow keys to choose and Enter to open.

Notes

Why Startups Keep Missing Deadlines: The Real Cause Behind Sprint Delays, Missing Test Cases and Forgotten Features

Why startups miss deadlines: unclear work, scope creep, weak testing, missing documentation, and poor planning create delivery failure.

Created 2026-09-17 · Updated 2026-09-18 · 16 min read
Learningagilestartupssprint-delaysmissed-deadlinesscope-creepacceptance-criteriadefinition-of-readydefinition-of-donestory-pointsvelocitycapacitytestingtest-casesfeature-ownershipdocumentationbacklog-refinementsprint-planningazure-devopsai-developmentsoftware-qualityproduct-deliverymaintainabilitycontinuous-improvement

The questions that keep repeating

Sit in any startup review meeting and the same questions come back every month:

  • Why did we miss the deadline again?
  • Why does every sprint end with unfinished work?
  • Why do we have a hundred features and test cases for maybe ten of them?
  • Why does nobody in the team know all the corner cases of a feature we ourselves built six months ago?
  • Why does a small new feature break something in a completely different screen?
  • Why was the estimate fine on paper and completely wrong in reality?

Management asks these questions expecting a people answer: the developers were slow, the tester missed it, the manager did not follow up. And so the fix that gets applied is also a people fix: more status meetings, more pressure, more tracking in Azure DevOps.

But these are not people problems. They are all the same system problem wearing different clothes.

The honest answer

We spend almost all our energy on building features, and almost none on defining, testing, documenting and maintaining them.

Building feels like progress. You can see it. You can demo it. You can tell yourself at the end of the week, “we shipped inventory management in seven days”. That feeling is real and it is also a trap, because what you actually shipped is:

  • code that works for the three cases you thought about,
  • no written record of what it is supposed to do,
  • no test cases beyond a manual click through,
  • and a set of edge cases that exist only inside one developer’s head for as long as that developer remembers them.

That is not a finished feature. That is a liability with a nice UI. And liabilities compound. One of them is fine. Forty of them is a product where nobody can change anything safely, every release needs a week of manual regression, and every estimate is a guess because nobody knows what will break.

Short term happiness becomes long term burden by simply adding up.

The loop we are actually stuck in

Draw our real process honestly and it looks like this:

flowchart TD
    A["Requirement<br/>(half defined)"]
    B["Development starts immediately"]
    C["Stakeholder sees a demo<br/>and gives feedback"]
    D["Existing item silently grows"]
    E["Estimate becomes meaningless"]
    F["Sprint gets overloaded"]
    G["Items carry forward"]
    H["Next sprint starts with<br/>old unfinished work"]
    I["Deadline slips again<br/>and trust decreases"]

    A --> B
    B --> C
    C --> D
    D --> E
    E --> F
    F --> G
    G --> H
    H --> I
    I --> A

Notice that no single step in this loop is stupid. Every step is a reasonable person doing a reasonable thing. The stakeholder is right to give feedback. The developer is right to want to satisfy the stakeholder. The manager is right to want it in this sprint. The loop is destructive not because anyone behaves badly, but because nobody is defending the boundary of the work.

The important thing to understand: the problem is not Agile. The problem is uncontrolled Agile.

Agile says requirements are allowed to evolve. It never said every new idea should immediately expand whatever a developer is currently coding. The Scrum Guide is explicit that scope can be clarified and renegotiated with the Product Owner during a Sprint, but changes must not endanger the Sprint Goal. We took the first half of that sentence and threw away the second half. That is the whole story of our delays, and the fix for it lives in Feedback and Scope Control.

What AI changed, and why it made this worse

AI did not create this problem. It accelerated it.

Before AI, bad planning was throttled by slow typing. If a requirement was vague, it took three weeks to build the wrong thing, and somewhere in those three weeks a developer would come back and ask, “what should happen if the invoice is already paid?”. The slowness of coding was accidentally acting as a requirements review.

Now the code arrives in an afternoon. The vague requirement goes in, a large amount of plausible working code comes out, and nobody was forced to ask the awkward question. So:

  • Feature output went up several times over.
  • Requirement clarity, test coverage and documentation stayed exactly where they were.
  • The gap between “how much product exists” and “how much product we understand” grows every single week.

That gap is the thing that eventually stops a startup. You do not notice it at 10 features. At 60 features it is the reason a two day change takes two weeks. I have written what specifically changes in an AI heavy team in Building with AI, because the answer is not “use AI less”. The answer is that the planning and the specification are now the scarce resource, not the code.

The five root causes

Everything in the loop traces back to five specific failures. Each one has its own note, because each one has its own fix.

1. We start building before the work is defined

Our usual unit of work is a line in a sprint board that says “Inventory Management”. That is not a task. That is a business objective, and a developer cannot finish an objective, cannot estimate an objective, and a tester certainly cannot write test cases against an objective.

“Inventory management” should have been an Epic, broken into Features, broken into User Stories, broken into Tasks. Only at the Story level does a sentence appear that a tester can turn into test cases, like “as a store manager I want to be warned when a sale takes stock below zero so that I do not sell what I do not have”. That whole decomposition discipline, with the rules for deciding which level a piece of work belongs to, is in Work Breakdown Hierarchy, and the craft of writing the Story itself is in Writing User Stories.

This single mistake, defining work at the wrong altitude, is responsible for most of the others. Bad decomposition is why estimates are wrong, why test cases do not exist, and why “done” is negotiable.

2. We never wrote down the expected behaviour

When a Story enters development with no written Acceptance Criteria, the expected behaviour lives in a conversation that happened once. Then the demo happens and the stakeholder says “that is not what I expected”, the developer says “that is what I understood”, and both of them are telling the truth. There was no agreed definition to compare against, so there is no way to prove the work is finished, and the Story reopens.

Acceptance criteria are not bureaucracy. They are the only artifact that lets you say the word “done” without arguing. They are also, and this is the part people miss, the raw material for your test cases. No acceptance criteria means no test cases, and that connects directly to the next cause.

3. We absorb feedback instead of classifying it

This is the mechanism that actually eats our sprints.

The Story was “export invoice as PDF”, estimated at 5 points. The stakeholder sees the demo and says: “nice, can we also export Excel and CSV, and email it to the customer directly?”

What we do today: add three more tasks under the same Story. The 5 point Story quietly becomes a 20 point Story. Nobody records that this happened. At the end of the sprint the Story is incomplete, and the conclusion in the retro is “our estimates are bad”.

Our estimate was not bad. We estimated A and delivered A+B+C+D.

Not all feedback is the same thing, and treating it all the same way is what kills predictability. Feedback can be a defect, a clarification, new scope, a genuine requirement change, an urgent production interrupt, or a nice idea for later. Each of those deserves a different response, and exactly one of them belongs inside the current Story. The classification table for this, and the one policy sentence I want printed on the wall, are in Feedback and Scope Control.

4. We treat testing as a phase that happens later

Testing after development is not a process. It is a hope.

When testing is a separate later phase, it is the first thing that gets sacrificed when the sprint is tight, and it gets sacrificed silently. The feature ships anyway. The test case is never written, so six months later the only way to know how the feature should behave is to read the code and guess the intention.

That is precisely why we now have a large product with very few test cases. It was never one big decision. It was two hundred small skips. The fix is to make test cases fall out of the acceptance criteria automatically, and to make “tested” part of Definition of Done rather than a separate optional stage. The complete approach, including how to attack the backlog of untested features we already have, is in Test Case Strategy.

5. We keep the product’s knowledge inside people’s heads

Ask the team “what happens if a bank feed transaction is categorised, then the bank changes it from pending to posted?” and you will get either silence or three different answers. That knowledge existed at the moment of building. It was never externalised, so it decayed.

When knowledge lives in heads: onboarding a new engineer takes months, the person who built the module becomes a bottleneck for every change to it, and when they leave, the feature effectively becomes unowned legacy code that nobody dares to touch. A product is not just its code. It is its code plus the written behaviour, edge cases, decisions and ownership around it. How to build that catalog without turning into a documentation factory is in Feature Inventory and Ownership.

Stop saying “our estimates were wrong”

When a sprint fails, “the estimate was wrong” is the laziest possible diagnosis, because at least four completely different failures hide behind it, and they have four completely different fixes:

| What actually happened | The real failure | Where the fix lives |

Observation What it means Related note
The work was technically harder than anyone expected Genuine uncertainty. Acceptable, sometimes. Estimation and Story Points
Nobody was sure what was being asked for Refinement failure Definition of Ready
The requirement grew after coding started Scope control failure Feedback and Scope Control
We simply pulled in more than we have ever delivered Planning failure Velocity and Capacity

If you collapse all four into “developers estimate badly”, you will attack the one thing that was probably fine and never fix the three that were broken. In the retrospective, the useful question is never “why was the estimate wrong”. It is “which of these four was it, and what is the evidence?”

What the fixed loop looks like

Same picture, with the boundaries put back in:

flowchart TD
    A[Idea / Requirement]
    B[Backlog Refinement<br/>clarify, split, write acceptance criteria, find dependencies]
    C{Definition of Ready met?}
    D[Estimated by the team]
    E[Sprint Planning<br/>Sprint Goal set, pulled against real velocity and capacity]
    F[Development + tests written alongside]
    G[Feedback arrives]
    H{Classify feedback}
    I[Defect<br/>fix here]
    J[New scope<br/>create new backlog item]
    K[Urgent<br/>PO trades something out explicitly]
    L[Acceptance criteria pass<br/>+ Definition of Done met]
    M[Done<br/>behaviour is written down where the next person can find it]

    A --> B
    B --> C
    C -- No --> B
    C -- Yes --> D
    D --> E
    E --> F
    F --> G
    G --> H
    H --> I
    H --> J
    H --> K
    I --> L
    J --> B
    K --> F
    F --> L
    L --> M

The difference between the broken loop and this one is not effort and it is not tooling. It is that three gates exist: Definition of Ready before work starts, Acceptance Criteria to decide the Story is correct, and Definition of Done to decide it is genuinely complete. Our current process has zero gates, which is why anything can flow in at any time.

The rules I want to live by

These are the things I would write on the wall. Everything else in these notes is supporting detail.

  1. Nothing enters a sprint without acceptance criteria. If we cannot say what it should do, we cannot say when it is done, and we are not ready to start.
  2. Feedback that adds new capability becomes a new backlog item, not a bigger current Story. Always. The only exception is when the Product Owner explicitly trades something else out of the sprint, out loud, in front of the team.
  3. A Story is Done or it is not Done. There is no 90%. Partial work earns zero points. This is uncomfortable for exactly two sprints, and then it starts telling you the truth about your Story sizes.
  4. The Sprint Goal is the thing we defend. Individual tasks can change. The goal does not.
  5. Test cases are written from acceptance criteria, in the same Story, by the time it is Done. Not in a “testing sprint” that will never be scheduled.
  6. Story points measure size and uncertainty, never hours, and velocity is a forecasting tool, never a performance target. The moment velocity becomes a target, the numbers inflate and you lose your only planning instrument. See Velocity and Capacity.
  7. If a feature’s behaviour is not written down anywhere, the feature is not finished, no matter what the code does.

How to actually take action

Do not try to adopt all of this at once. It will fail, and the failure will be used as evidence that “process does not work here”. Change one thing at a time, in this order, because each step makes the next one possible.

Week 1. Make the problem visible. Stop arguing from feelings and get one number: for the last three sprints, how many items carried forward, and for each one, which of the four causes above was it? This takes an hour with the board open. Present it as a table. This single table changes the conversation from “developers are slow” to “70% of our rollover was scope added mid sprint”, which is a problem that has an actual fix.

Week 2. Introduce one gate: acceptance criteria. Pick the next five Stories. Nothing enters the sprint until it has written acceptance criteria. Do not introduce points, poker, DoR, DoD or anything else yet. Just this one thing. Use the formats in Acceptance Criteria and the copy paste blocks in Templates.

Week 3. Start classifying feedback. Every time feedback arrives mid sprint, somebody says out loud which of the six categories it is, and the new scope ones go to the backlog. Use the table in Feedback and Scope Control. Expect friction here. This is the step that actually fixes the delays, and it is also the step people resist, because for the first time somebody is saying “not in this sprint”.

Week 4. Fix the decomposition. Take your current sprint board and re-cut it using Work Breakdown Hierarchy. Most “tasks” will turn out to be Features containing four or five hidden Stories. This is usually the moment the team realises why estimates never worked.

Month 2. Add the gates and the measurement. Write a first Definition of Ready and Definition of Done as short checklists, seven items maximum each, and improve them later. Start estimating Stories with Estimation and Story Points, and after three sprints start using Velocity and Capacity to plan instead of using optimism.

Month 3. Close the quality gap. Make test cases part of Done using Test Case Strategy, start the behaviour catalog in Feature Inventory and Ownership for the five features that break most often, and if you run anything in production that people depend on, define your first two or three service level objectives using SLI SLO and Error Budget.

The concrete week by week version of this, with what to say to stakeholders and what to do when someone pushes back, is in Adoption Plan. If you run all of this in Azure DevOps, the exact work item types, fields, tags, queries and boards that support it are in Azure DevOps Setup.

How you will know it is working

Watch these four, not “are people busy”:

  • Carry over rate: percentage of committed points not finished. Should fall and then stay stable. Stability matters more than the number.
  • Mid sprint scope added: points added after the sprint started. This is the one that proves whether rule 2 is actually being followed.
  • Stories that entered the sprint without acceptance criteria: should reach zero and stay there.
  • Behaviour coverage: percentage of live features that have written acceptance criteria and at least one test case. This one only moves slowly, and it is the number that decides whether you can still move fast in a year.

If those four move in the right direction, deadlines stop being a fight, because you will be promising things you have evidence you can deliver.

The point of all of this

A feature is not successful because it was coded quickly. A feature is successful when, six months later, a person who did not build it can still answer: what is this supposed to do, how do I know it works, what breaks if I change it, and who owns it.

The wrong question is “how fast can we build this?”

The right question is “how do we build this so that it is still understandable, testable and changeable when the product is five times bigger?”

That difference, between fast coding and actual product engineering, is the whole reason I wrote these notes. Start with the terminology in Glossary if the words are the blocker, or go straight to Work Breakdown Hierarchy if you are ready to fix how we cut up work.