Tag: linear

  • 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.

  • How we unbreak a Wednesday sprint without cancelling it

    How we unbreak a Wednesday sprint without cancelling it

    Every team we know has had that sprint. Monday standup looked fine. Tuesday morning a payment webhook started dropping in staging, one engineer went out sick, and the design review pushed the checkout redesign back by two days. By Wednesday afternoon the burndown on our Linear board was flat, six tickets deep, and the sprint goal read like fiction.

    We used to cancel sprints in this situation. We stopped doing that around a year ago. Cancelling costs us the retrospective, the sense of finishing something, and the muscle memory of shipping on a cadence. What replaced it is a Wednesday recovery ritual that we run in about forty minutes.

    The Wednesday triage, not another standup

    We block thirty minutes on Wednesday at 2pm called “Sprint check”. It only fires when the burndown deviates more than twenty percent from the ideal line, which our Datadog dashboard flags in a Slack channel called #eng-signals. If the sprint is on track, the meeting is cancelled by 1:45pm and nobody joins.

    When it does fire, three people attend: the engineering lead for the squad, the product manager, and whoever picked up the on-call pager that week. No designers, no wider group. The point is a fast, honest read on the remaining ten working hours across four engineers.

    The question we ask is not “can we still finish everything?” It is “what one thing, if shipped by Friday, would make this sprint worth having run?”

    That one question forces a decision that the daily standup rarely produces. Standups report status. Wednesday triage rewrites the plan.

    Cut scope in the second half

    Once the anchor ticket is named, we walk the remaining Linear tickets and sort them into three buckets. We do this on a shared Notion page titled “Sprint 47 midweek reset” with three headings and drag ticket links under each.

    1. Ship this week. The anchor ticket and anything on its critical path. Usually two or three tickets.
    2. Defer to next sprint. Work that is not blocking anyone. Move it back to the backlog with a comment explaining why.
    3. Drop, do not defer. Tickets that felt urgent on Monday and no longer do. These get closed with a short note. If they matter again, someone will reopen them.

    The third bucket is the one that saves us. Roughly a quarter of what we plan on Monday gets dropped rather than deferred, and none of it has come back to bite us in the four sprints we have tracked this pattern.

    Slice the anchor, do not shrink it

    The highest value ticket is where teams tend to lie to themselves. On Wednesday we do not promise a smaller version of the same scope. We split the ticket into two Linear issues, and the parent becomes an epic.

    Take our checkout redesign example. The original ticket read: “Ship the redesigned checkout flow with saved cards, address autofill, and Apple Pay.” By Wednesday it was clear we had ten hours of engineering work left and about twenty hours of scope. The split looked like this:

    • PAY-412: Ship the redesigned checkout behind a feature flag, five percent rollout, saved cards only. Owner: Priya. Estimate: eight hours.
    • PAY-413: Address autofill and Apple Pay under the same flag. Owner: unassigned. Moved to next sprint.

    The slice we ship on Friday is a real, running thing in production, even if it sits behind a flag at five percent. Next sprint we widen it. What we avoid is the trap of promising the whole checkout by Friday, then delivering nothing and calling it a spike.

    The rolling change log

    Every scope change goes into a single Notion page we call the Sprint Ledger. One page per sprint, appended to as things move. Each entry has a timestamp, the ticket ID, what changed, and one line of why.

    Wed 14:32  PAY-401  Dropped. Duplicated by PAY-397 already in progress.
    Wed 14:35  PAY-412  Split from PAY-388. Anchor for the week.
    Wed 14:41  ONB-215  Deferred. Blocked on design; no unblock this week.

    The ledger takes about six minutes to fill in during triage. It is read twice: once by the wider squad on Wednesday afternoon, and once by the retro facilitator on the following Monday. Nobody hunts through Slack scrollback trying to remember what changed and why.

    What we get back

    Four things, measured over ten sprints since we started running this ritual:

    • We now finish about eighty percent of our stated sprint goal by Friday, up from around fifty percent when we would grind on the original plan or cancel outright.
    • Retros focus on cause, not blame. The ledger tells us what happened; we can talk about why.
    • Product managers push back less on Wednesday cuts, because the anchor is preserved and the ledger makes the trade visible.
    • On-call load in the second half of the sprint dropped, because we stopped shipping half finished work under time pressure.

    None of this requires new tooling. Linear, Notion, Slack, one recurring calendar block, and a rule about when it fires. The hardest part is not the process; it is the willingness on Wednesday afternoon to say out loud that Monday’s plan is no longer the plan, and to write down what replaced it before the day ends.