Tag: cycles

  • How we handle mid-cycle scope creep without cancelling the cycle

    How we handle mid-cycle scope creep without cancelling the cycle

    Every two-week cycle at Velo starts with a plan we believe. By Wednesday of week one, something has usually shifted. A support pattern turns into an incident. A customer contract lands with a hard integration date. A design review surfaces a flaw that means the header refactor is bigger than we scoped. The temptation, when this happens, is to either pretend nothing changed and burn the team out, or blow up the cycle and replan from scratch. We do neither.

    Instead we run a small, boring ritual every Wednesday at 11:00 called the mid-cycle trim. It takes 30 minutes, involves the tech lead and the PM for each squad, and follows the same three moves every time. Here is what we do, and why the ritual survived four quarters when almost nothing else in our process did.

    The three moves

    We treat the cycle as a fixed container. If new work goes in, existing work comes out. That constraint is the whole game. The Wednesday trim is where we honour it.

    1. Cut the two lowest-value items still open. We pull up the Linear cycle view, sort by our internal priority score, and mark the bottom two tickets as cycle: deferred. They keep their estimates and their context; they lose their promised delivery date. If a ticket is already in review, we leave it; the cost of context-switching outweighs the saving.
    2. Split the highest-value item into a smaller slice. The biggest ticket in the cycle is usually the one hiding the most risk. We ask the engineer working on it: what is the smallest piece of this that a real customer can use on Friday of week two? That becomes the new scope. The rest becomes a follow-up ticket, linked, with the notes carried across.
    3. Log the trade in the rolling scope-change page. We keep one long Notion page per quarter titled Scope changes, Q3. Every trim adds a row: date, cycle number, what came in, what came out, who decided, one sentence on why. No approvals, no drama. A record.

    That is the whole ritual. Cut two, split one, log the trade. We finish by 11:30 and post the diff in the squad Slack channel by lunch.

    Why each move earns its place

    The cuts exist because engineers will not admit a ticket is low value while it is theirs. Naming the bottom two of the list, out loud, in the same meeting every week, removes the social cost. Nobody has to argue for their pet feature to survive. They only have to argue against a specific cut, and if they cannot, the cut stands.

    The split exists because our worst cycles were always the ones where the biggest ticket slipped by three days and dragged three smaller ones with it. Forcing a Friday-of-week-two slice on the largest ticket surfaces the risk while there is still time to react. The engineer often finds the slice is 40 percent of the work and delivers 80 percent of the value, which is a good trade even without a scope crisis.

    The log exists because we used to have the same argument every quarter about whether the team was under-delivering. Now we open the Notion page in the retro and count. Last quarter we absorbed 23 mid-cycle changes across six squads without extending a single cycle. That number ended a lot of arguments.

    What we do not do

    A few things we tried and dropped:

    • We do not require the CTO or a product lead to approve trims. The squad decides. If the squad is wrong, we catch it in retro, not in a gate.
    • We do not track “scope creep” as a metric per squad. It punishes the teams closest to customers, which is the opposite of what we want.
    • We do not roll deferred tickets automatically into the next cycle. They go back to the backlog and compete on merit. About a third never come back, which tells us the trim was correct.
    • We do not run the trim on Monday. Too early, the picture is still forming. Or Friday. Too late, the week is already lost. Wednesday is the fulcrum.

    What it looks like in practice

    Two weeks ago, the billing squad walked into Wednesday with a fresh Datadog alert showing invoice PDFs failing for 4 percent of enterprise customers. They cut a small copy update on the settings page and a nice-to-have export format. They split the ongoing tax-rate refactor: ship the US states this cycle, hold EU VAT for the next one. They logged three lines in the Notion page. The incident work landed on Thursday of week two. Nobody worked a weekend.

    That cycle looked, from the outside, like a normal cycle. That is the point. The ritual is not glamorous, and it does not solve the underlying question of why new work keeps arriving. It gives us a repeatable way to say yes to the important new thing without lying to ourselves about the cost. We recommend stealing it.

  • The five-day slice rule

    The five-day slice rule

    Every Monday at 10:15 our delivery lead opens Linear and runs a filter called Cycle Ready. If a ticket in the active cycle fails the filter, it gets flagged red and the ticket owner has until standup Tuesday to fix it or pull it. The filter checks one thing: can a single engineer start work Monday morning and demo something running by Friday afternoon.

    We call this the five-day slice rule. It has been the single biggest change to how our team ships since we moved off two-week sprints eighteen months ago.

    Why five days, not ten

    We tried ten-day cycles for most of 2024. Tickets came in sized small, medium, or large, and engineers estimated them in points. By day seven of a typical cycle, roughly a third of medium tickets were still labelled In Progress with no visible artifact. Reviewers had nothing to look at. QA had nothing to queue. The last three days always became a scramble.

    The pattern was consistent enough that we started tracking it in Datadog against our Linear webhook data. Tickets that produced no reviewable artifact by day three of a ten-day cycle had a 72 percent chance of slipping the cycle. Tickets that did produce something by day three slipped 8 percent of the time. The signal was loud.

    We cut the cycle in half and enforced a hard rule on entry: one person, Monday start, Friday demo. If it does not fit, split it before the cycle starts, not during.

    How we enforce the rule

    The rule lives in three places:

    • A Linear template with a required field called Friday demo artifact. Engineers cannot move a ticket into Ready for Cycle without filling it in. Sample entries: a PR merged behind a flag and hitting a staging endpoint; a Grafana panel showing p95 for the new route; a Loom of the empty state rendering with fixture data.
    • A pre-cycle review meeting on Friday afternoon called Slice Check. Twenty five minutes, four people: engineering manager, tech lead, product manager, delivery lead. We read the Friday demo artifact field for every candidate ticket. If anyone at the table cannot picture the demo, the ticket does not enter.
    • A Slack bot posting into the delivery channel every Wednesday at 4pm with the list of active-cycle tickets that have no PR opened and no draft artifact linked. The message pings the ticket owner directly.

    The bot is the piece that took the longest to trust. We tuned it for six weeks before people stopped arguing with it. The current heuristic: no draft PR, no Loom link, no Notion doc updated in the last 48 hours, and the ticket is past cycle midpoint. Three signals, one ping.

    What happens when a team pushes back

    The rule gets fought. Usually by whichever team is holding the largest piece of unsplit work. We have heard every version of the objection:

    You cannot split a database migration into five-day slices. The migration either runs or it does not.

    The auth rewrite is one atomic change. Splitting it means shipping something broken.

    We are being asked to do more planning work than shipping work.

    We take these seriously and we still hold the line. Every migration we have run in the last year has split. Every auth change has split. The planning cost is real and it front-loads. Our data shows the front-loaded planning cost is roughly 90 minutes per split ticket, and it saves an average of 6 hours of end-of-cycle scramble per unsplit ticket that slips.

    When a team insists a piece of work cannot split, we sit down with them for a 30 minute session with a whiteboard and the delivery lead. We have run this session 41 times. It has produced a valid split 39 times. The two exceptions were a vendor cutover with an external deadline and a hotfix that shipped inside a day.

    A concrete example: splitting the profile export ticket

    Last quarter we had a ticket that read: add data export for user profiles, including preferences, integrations, activity history, and audit logs, downloadable as a signed ZIP. Original estimate: two weeks. Owner: one engineer on the Growth pod.

    Under the old rules this would have entered a cycle whole. Under the slice rule we ran it through Slice Check on the Friday before, and split it into three tickets:

    1. Slice one, week of Jan 13. Endpoint scaffold plus preferences payload. Friday demo: hit POST /exports/profile in staging, receive a signed URL, download a ZIP containing a single preferences.json file. Behind a flag. One engineer, five days.
    2. Slice two, week of Jan 20. Add integrations and activity history to the payload. Friday demo: same endpoint, same flag, ZIP now contains three files. Handles the 90 percent case of activity records fitting in a single query batch.
    3. Slice three, week of Feb 3. Audit logs, pagination for large history sets, signed URL expiry policy, and flag flip. Friday demo: end to end run for a real customer account with 40k audit rows, timing recorded in the demo doc.

    We put a two-week gap between slice two and slice three on purpose. That gap ran a quiet beta with three friendly customers on slice two, and the feedback moved the audit log format before we built it.

    Total calendar time: roughly the same as the original two-week estimate would have been had it not slipped. The difference is that we had something demoable at three checkpoints instead of one hopeful checkpoint at the end.

    What we track

    We keep three numbers on a Notion page called Delivery Health:

    • Percent of active-cycle tickets that hit their Friday demo artifact. Current: 88 percent, target 85.
    • Median time from a ticket entering Ready for Cycle to its first PR opened. Current: 1.2 days.
    • Number of tickets that entered a cycle unsplit and slipped. Current: 2 this quarter, down from 14 the same quarter last year.

    The rule is not magic. It is a constraint that forces the planning conversation to happen on Friday instead of Wednesday of week two, when a slip is already priced in. If the demo cannot be pictured on Friday, the work is not ready. That is the whole rule.