Tag: metrics

  • Why we stopped tracking hours

    Why we stopped tracking hours

    We killed the timesheet in March. Nobody misses it. What replaced it made our finance team nervous for about six weeks, and then it stopped making them nervous. Here is what happened.

    What we track now

    We stopped asking engineers, designers, and PMs to log hours against project codes in Harvest. It rewarded the wrong thing: presence. A person could sit on a Linear ticket for three days, log 24 hours to it, and produce nothing shippable. The timesheet said the work was funded. The product said otherwise.

    We now track two things per squad, weekly, in a Notion database that pulls from Linear and GitHub:

    • Shipped units of work: tickets that closed the loop, meaning code merged, feature flagged on for at least one real customer, and no rollback within seven days.
    • Cycle time: median days from “In Progress” to “Shipped” on Linear, per squad, broken out by ticket size (S, M, L).

    That is it. No story points. No hours. If a squad shipped four medium tickets in a week with a cycle time of 3.2 days, that is the artifact. We review it every Thursday in a 25 minute meeting called Ship Review.

    What finance pushed back on

    Our CFO’s first question was fair: how do we capitalize engineering costs for the R&D credit if nobody is logging hours to projects? HMRC wants a defensible allocation. Auditors want a paper trail. “The vibes were good on Thursday” is not a paper trail.

    Her second question was harder. If a contractor bills us for 40 hours and we have no internal hours to compare against, how do we know we are not being overcharged?

    What we told them

    We proposed a trade. Finance gets a defensible model. Squads keep their calendars.

    1. Every squad has a fixed roster, and every roster maps to one or two product areas in a Notion table. Payroll cost per squad is known. That is our allocation basis, reviewed quarterly.
    2. Contractors still log hours in Harvest, because they bill by the hour. Employees do not, because they do not.
    3. The Ship Review output feeds a monthly note to finance: shipped units, cycle time trend, and any squad where cycle time doubled without a headcount change. That flags stuck work faster than a timesheet ever did.

    Six months in, our R&D claim went through without a query. Cycle time on our payments squad dropped from 8.1 days to 4.4. Nobody has asked to bring hours back.

    A timesheet measures whether you showed up. A shipped ticket measures whether the customer got something.

    We know which one we would rather report on.

  • Velocity is a lie detector not a speedometer

    Velocity is a lie detector not a speedometer

    Every quarter we watch another engineering team roll a velocity chart into a review deck, gesture at the bars trending up and to the right, and declare progress. We used to do it too. Then we ran a small experiment on our own Velo delivery team: we hid the velocity number from three squads for a full quarter and gave them cycle time instead. Two of the three squads shipped more features. All three reported that planning felt less theatrical.

    This is not an argument against measurement. It is an argument against a specific metric that has quietly stopped telling us what we think it tells us.

    Velocity measures the ruler, not the road

    Story points are a ruler the team invented. When we grade a team on how many units of their own ruler they produce per sprint, we should not be surprised when the ruler starts stretching. We have watched this happen on our own boards. A ticket that would have been a 3 in April becomes a 5 by July. Nobody lies. Everyone remembers “that thing that turned out harder than expected,” and the estimate drifts up. The chart climbs. The output does not.

    Goodhart’s law shows up in the standup:

    When a measure becomes a target, it ceases to be a good measure. Velocity is the most polite example of this rule we have found in software.

    The other failure mode is subtler. Velocity averages hide the shape of the work. A team can hit 42 points every sprint for six sprints and be quietly falling apart, because 40 of those points come from a single engineer who is one Slack DM away from resigning. The bar chart cannot see that. Cycle time can.

    Cycle time is boring, which is the point

    Cycle time is the elapsed clock between “in progress” and “done.” It is boring because it measures reality rather than an estimate. We cannot inflate it by talking about it in a Wednesday grooming session. It refuses to care about our narrative.

    Here is the comparison we now put in front of every engineering lead we hire:

    • Unit. Velocity uses story points, a team invented currency. Cycle time uses hours or days, a currency everyone shares.
    • Gameable by. Velocity is inflated by re estimation, ticket splitting, and status theatre. Cycle time is inflated only by shipping faster, which is what we wanted.
    • Sensitive to. Velocity is sensitive to who is in the room during planning poker. Cycle time is sensitive to review queues, environment flakiness, and handoffs, the things that slow us down.
    • What it hides. Velocity hides bottlenecks behind an average. Cycle time exposes them by widening the tail of the distribution.
    • Actionable signal. A dropping velocity prompts a debate about commitment. A widening cycle time prompts a debate about the pull request that has been open since Tuesday.

    What we changed on our own board

    We run Linear for tickets and pipe every state transition into a Datadog dashboard. Once a week, on Thursday afternoon, we look at three numbers together:

    1. Median cycle time for tickets closed that week.
    2. The 90th percentile of the same distribution.
    3. The count of pull requests older than 48 hours.

    We deliberately do not look at velocity anymore. When a stakeholder in Notion asks “how much did we ship this quarter,” we answer with a count of shipped tickets and a link to the changelog. If they push, we show the cycle time trend. Nobody has pushed twice.

    The 90th percentile is the metric that changed our behaviour the most. Medians are polite. They hide the ticket that sat in code review for eleven days because the reviewer was on parental leave and nobody rerouted it. The 90th percentile has forced us to build a bot in Slack that pings the review channel every morning at 9:15 with any pull request older than a day. Our median moved a little. Our tail moved a lot.

    The objections we still hear

    Two objections show up in every conversation about this, and both deserve a real answer.

    The first is that cycle time punishes big work. A refactor that takes two weeks will show up as a fat cycle time number and drag the median. Our response: split the refactor. Not into fake tickets that ship in isolation, but into shippable, reversible steps. If a piece of work cannot be split, that is itself a finding, and the fat number is telling us something true.

    The second objection is that cycle time can also be gamed. Engineers can open tickets late, close them early, or keep everything in draft. Fair. We have seen all three. The difference is that these games are visible in the version control log and in the Linear activity feed. Velocity inflation is invisible, because the ruler itself is invisible. A gamed cycle time becomes a conversation. A gamed velocity becomes a slide.

    The metric we would keep if we could only keep one

    If a new engineering leader joined tomorrow and asked which single number to track, we would not hesitate. Track the 90th percentile of cycle time, week over week, and set a target for the tail rather than the average. That number is close enough to reality that people can argue about it usefully, and far enough from planning theatre that it does not warp under pressure. Velocity charts belong in a museum next to lines of code per day. We stopped drawing them and started drawing something harder to fake.