Skip to content
Sudip KC writing notes in a journal at a desk
SK.
← All articles

Career · · 6 min read

How I Estimate Software Projects

  • Career
  • Leadership
  • Productivity
  • Architecture

Every estimate I gave early in my career was really a guess about the parts I understood, with the parts I did not understand quietly set to zero. That is why they were always wrong in the same direction.

Estimation used to be the thing I dreaded most. A client or a manager would ask "how long will this take?" and I would feel pressure to say a number that sounded confident and small. Then the project would run long, and I would work weekends to make my own guess look less wrong.

Since moving into a technical project manager role at NovaNext, estimating is a big part of my job. I still get it wrong sometimes. But I get it wrong less, and more importantly, I get it wrong in ways I can explain early instead of at the deadline. Here is the process I use.

First, decide what kind of estimate you are giving

People ask "how long?" in very different situations, and the right answer changes.

  • A ballpark for someone deciding whether an idea is worth pursuing at all. Here a range like "four to eight weeks" is honest and useful.
  • A planning estimate for a scoped project with a known team. This is where most of the work below goes.
  • A sprint-level estimate for tasks the team will start this week. Small, concrete, and easy to correct.

The worst mistake is giving a ballpark answer in a hallway and then watching it become a contract. These days, when someone asks for a quick number, I say the range out loud and add "that is a rough guess before I have seen the details." It feels awkward. It saves a lot of pain later.

Break it down until the pieces are boring

You cannot estimate "build a restaurant management system." You can estimate "build the table reservation form with date, time, party size, and validation."

I break the project into features, then each feature into tasks small enough that I can picture the code. My rough rule: if a task feels bigger than two or three days, it is hiding something, and I split it again.

For a feature like split billing on a platform like NovaRestro, the breakdown might look like this:

  1. Data model for bill splits and payment allocations
  2. API endpoints with permission checks per role
  3. UI for choosing split type: equal, by item, by custom amount
  4. Handling rounding so the parts always add up to the total
  5. Receipt printing for each split
  6. Edge cases: refunds, voids, an item moved between splits
  7. Tests and QA

Looking at that list, it is obvious that "rounding" and "edge cases" are where the time goes. Before the breakdown, I would have estimated the UI and forgotten the rest.

Estimate in ranges, not single numbers

For each task I write two numbers: a likely case and a pessimistic case. Not an optimistic one, because my optimistic case is basically my likely case anyway.

  • Familiar CRUD on an established pattern: tight range, maybe one to two days.
  • Something with a third-party integration, like an eSewa or Khalti payment flow: wide range, because the sandbox, the docs, and the callbacks always have surprises.
  • Anything I have never built before: very wide range, and a flag that says "spike first."

The width of the range is information. A project made of tight ranges is predictable. A project with a few very wide ranges has risk concentrated in specific places, and those places should be tackled first.

A single number hides the uncertainty. A range shows people exactly where the risk lives.

Spike the scary parts

When a task has a range like "two days to two weeks," I do not average it. I propose a time-boxed spike: one or two days to build the ugliest possible proof that the risky part works.

Offline waiter ordering is a good example. Syncing orders taken without network back to the server, without duplicates, with conflicts handled, is not something I would estimate cold. A short spike tells me whether the approach holds up and turns a two-week range into something much tighter.

Spikes also make conversations with stakeholders easier. "I need two days to find out" is a much better answer than a confident number I do not believe.

Add what everyone forgets

My early estimates only counted writing code. Real projects include a lot more, and I now add these explicitly instead of hoping they fit in the gaps:

  • Code review and revisions. Reviews take time on both sides.
  • QA and bug fixing. Usually a meaningful chunk of the project, not a final afternoon.
  • Design back-and-forth. Even with a finished Figma file, questions come up during implementation.
  • Loading, error, and empty states. Always forgotten. I wrote a whole post on handling them properly.
  • Deployment and environment setup. Servers, domains, Nginx config, environment variables, backups.
  • Meetings and communication. Standups, demos, clarification calls.
  • Feedback cycles. The client sees it and wants changes. They always do.

I keep these as their own line items rather than a mysterious "buffer," because a buffer gets negotiated away. A line called "QA and fixes" is harder to delete.

Account for the team, not an ideal developer

An estimate depends on who is doing the work. A task that takes a senior developer one day might take an intern three, and that is fine, because the intern is learning and the senior developer is not free.

When I estimate for the team, I think about who will likely pick up each piece, how much context they have, and how much review and mentoring time it needs. I also do not plan people at 100%. Nobody spends eight focused hours a day writing feature code, especially not someone who also reviews pull requests and helps others. Something like six productive hours is closer to reality, and on days with lots of meetings, less.

Share the estimate with its assumptions

An estimate without assumptions is just a number someone will hold you to. So I always send the list along with it:

  • What is in scope, and what is explicitly out
  • Which designs are final and which are still changing
  • Which integrations depend on someone else's access or documentation
  • What happens if requirements change mid-sprint

When something changes, I can point to the assumption that broke and re-estimate that part, instead of the whole project silently slipping. This is a big part of what I meant in The Hardest Part of Software Development Isn't Coding. The communication around the work is the work.

Track actuals and learn

The last step is the one most teams skip: comparing the estimate to what actually happened. Not to blame anyone, but to calibrate.

After each sprint I look at which tasks blew past their range and why. The patterns repeat. For me it is usually integrations, permissions logic, and anything involving real-time updates. Knowing that, I widen those ranges next time before anyone has to ask.

What I'd tell you

Break the work down until it is boring, estimate in ranges, spike the parts you do not understand, and count the work that is not code. Then say your assumptions out loud and update the estimate the moment one of them breaks. You will still be wrong sometimes. But you will be wrong early, in public, with a reason, and that is what builds trust with clients and teams. If you are making the same shift into planning work, I wrote more about it in What I Learned Moving From Frontend Developer to Technical Project Manager.