Studio5 min read
What we quoted, and what it took
We went back through five finished engagements and compared the estimate to the hours. Three were close, one was 38% over, and the one that came in under is the one that bothers us.
Written by OZP Studios, Seattle, WA
Nobody asked us to do this. We were about to change our rate and it seemed dishonest to raise a number without checking whether the last several were any good.
The method was crude. Five engagements finished in the last two years, the figure in the estimate document against hours actually logged, plus the time we ate and didn't bill. The one still in progress isn't in the count, for the obvious reason.
Three were fine
Within about 10% either way, which for a fixed number written before the work starts we'll take. Two of those were phases that looked like things we'd built before, and one was a straight design system engagement where the scope was unusually easy to draw a line around.
Worth saying: two of the three had padding in them that we never mentioned to the client. Not a lot. Enough that “we estimated well” is a generous reading of what happened.
One was 38% over
An integration with a vendor API we hadn't personally worked with. We'd read the docs, the docs were fine, we priced it like a normal week of work.
Authentication alone took two weeks. Their sandbox accepted a token shape that production rejected, and it took nine days of back-and-forth with their support to get someone to confirm that yes, this is a known difference between the two environments. There was nothing clever to do about it. We couldn't test against production until we were live in production, and we couldn't trust the sandbox once we knew it lied.
It was fixed-price, so that was ours to absorb, and we did. The client's version of this project is that it shipped roughly on time, which is true and also not the whole thing.
One came in under, which is the one that bothers us
Roughly 20% under, because in week three we talked the client out of a feature we had already priced. They read that as a good outcome and told other people about it. We read it as evidence we'd quoted something we didn't believe in yet, and got lucky that the conversation happened early enough to be cheap. Coming in under on a thing you shouldn't have scoped isn't accuracy.
What we changed
Any integration against an API we haven't touched ourselves now gets priced as a short paid spike before the main number exists. A few days, fixed, and the deliverable is a memo about what's real. We've done two since. One came back saying the API was exactly as advertised and the phase price barely moved. The other came back saying the integration would roughly double the phase, and the client decided to defer that scope entirely, which is the best possible outcome for everyone and would not have happened if we'd quoted it blind.
The second change is smaller and more annoying. We don't track design time well. Engineering hours are clean because they're attached to branches and tickets; design hours disappear into conversations, revisions, and a Figma file nobody logs against. Until that's better, the range we put on a design-heavy phase stays wider, and we say why in the document instead of quietly hoping.
What we still don't know is whether the three that landed close were estimated well or just had slack in them. Two of five is a small enough sample that the honest answer is we'll find out on the next few, and we'll go back and check again.