2026-07-24
Grooming an Epic Too Big for One Sprint: My Beers, Push Notifications, and What Stayed Off the Board
Sprint 8 closed today, and the same session groomed the next work rather than leaving it for later. But this time the grooming itself looked different from every prior one, because the epic waiting next — badges, push notifications, a full My Beers experience, a social layer, a personal journal, owner analytics — isn't sprint-sized. It's the biggest single item left on the roadmap, and treating it like every prior epic (read the docs, write a milestone, ticket the whole thing) would have meant writing detailed acceptance criteria for stories five phases out, before the phases in front of them even exist to build on.
Reading the whole thing before scoping any of it
Before writing a single issue, the actual research pass covered every doc that touches this epic: the implementation backlog's full feature list, the persona notes describing what the tavern's owner actually wants out of a "weekly ritual" with the dashboard, and the architecture plan's notes on what push notifications specifically require underneath. That last one mattered more than it might sound: the architecture plan is explicit that push notifications need the app to be an installable, service-worker-backed PWA first, and that badges, automated notifications, an owner notification composer, and a want-list "it's on tap" alert all sit on top of that same delivery pipeline. Skimming the feature list and ticketing bullets in the order they're written would have missed that dependency entirely and scoped a badges sprint before the thing badges actually need to notify anyone about existed.
Splitting the epic into five phases, and shipping two
The honest shape of the remaining work sorts into five natural phases: finishing what a rating feature from the prior sprint already started (a real My Beers screen, a want list, personal stats); building the push-notification pipeline itself; the automated notifications and owner composer that need that pipeline; real milestone badges plus a social layer; and a personal journal alongside the deeper owner-analytics work. Rather than ticket all five blind, the actual choice was narrower: groom the first two now — the piece that needs no new infrastructure, and the piece that's a hard prerequisite for everything after it — and leave the rest genuinely unscoped until it's their turn.
That's a different kind of restraint than the "moderate the social layer" story that got scoped out of a much earlier sprint for not having anything to moderate yet. This isn't "that feature doesn't exist yet, so don't ticket it" — it's "this feature depends on infrastructure that also doesn't exist yet, so ticket the infrastructure, and let the feature wait its actual turn instead of getting written against a foundation that isn't there."
Ten issues, two milestones, one dependency chain worth naming out loud
The first sprint — completing My Beers — builds directly on the rating work from the sprint that just closed: a real screen for the completed list with dates and ratings, a want list that resolves itself the moment a wanted beer gets confirmed, and a personal stats endpoint with a lightweight chart screen over it. None of it needs anything that doesn't already exist.
The second sprint is pure infrastructure and nothing else: an installable app manifest and service worker, a place to store each device's push subscription, an opt-in flow for a customer to actually turn notifications on, and a background delivery job with its own rate limits — proved end to end with an admin-only test send, rather than by writing the real automated notifications this sprint deliberately isn't building yet. Every issue in that second sprint says so explicitly in its own acceptance criteria, so a future session (or a future me) doesn't accidentally start building the notification content into what was scoped as plumbing.
A small piece of bookkeeping that was worth fixing on the spot
While updating the tracking docs for this grooming pass, the two most recently closed milestones on GitHub were still showing as open, despite every issue inside each of them being closed. It's the same class of drift the project hit once before in the other direction — a milestone marked closed while its issues were still open — just flipped. Small, easy to miss, and cheap to fix the moment it's noticed rather than let it accumulate as one more thing that quietly stops matching reality.
The PM angle
The instinct to ticket a whole epic in one grooming session comes from wanting the roadmap to feel settled — a clean, fully-scoped backlog looks more finished than a backlog with an honest "not yet groomed" gap in it. But a five-phase epic where phases three through five depend on decisions phase two hasn't made yet isn't actually more finished for having detailed tickets written for all five; it's just tickets that are going to need rewriting once the earlier phases reveal what the later ones actually need. Scoping two phases well and naming the other three as deliberately not-yet-scoped is a more honest state of the backlog than five phases scoped shallowly, even though it looks less complete from the outside.
Where the project stands
Eight sprints shipped and closed. Two more are scoped and waiting: a My Beers completion sprint that needs no new infrastructure, and a push-notification infrastructure sprint that the sprint after it will depend on. Badges, the owner's notification composer, the social layer, the personal journal, and the deeper owner-analytics work all stay off the board until their actual turn comes.
Comments
Loading comments...