Tech Blog•
October 10, 2026
•
8 min read
•
2 views

Prioritising a Backlog When Everything Feels Urgent

Lucky
Design & Engineering
Diagram of a prioritisation flow with intake triage, capacity buckets by work class, scoring inside each bucket and a WIP-limited sprint

Executive TL;DR

  • Stop ranking unlike things against each other. Split the backlog by class of work — incidents and keep-the-lights-on, contractual commitments, strategic bets, debt and reliability — reserve a fixed share of capacity for each, and only then rank inside each class.
  • Make urgency a number instead of a tone of voice. Ask what it costs per week to not do this: a contractual deadline, a competitor window, a churn risk. Items with no answer are important but not urgent, and they stop winning arguments on volume alone.
  • Any score can be gamed, so protect the inputs. Confidence must be evidence-backed, effort must come from engineering not the requester, and the ranked list must be public. The output of prioritisation is a visible list of what you are not doing.

The week begins with a plan. Wednesday has seen an increase from the largest customer; sales have guaranteed a feature with a deal, an engineer has identified a database issue that will come to light in a month, and the strategic project everyone agreed on has not been touched. Someone proposes a prioritization framework.

Usually, the framework does not help, and it is worth understanding why. One ordered list is produced by a scoring system, which assumes everyone on it is comparable. It's not. The cost of an outage is immediate and unlimited. A contract commitment has a date and a legal consequence. A strategic bet has a large expected value and no deadline at all. A debt repayment this quarter has no apparent value but avoids a compounding cost next year. Put those four on one list, and the ones with near-term, visible pain always win. Not because they are most important, but because the cost of delaying them is the easiest to describe.

The second failure is more subtle. Most teams say urgency but don’t measure urgency. “This is urgent.” This is not a statement about the item; it’s a statement about the confidence of the speaker. Every scoring exercise is a vote they can influence, and the loudest stakeholder is driving the roadmap until someone asks what it costs per week to not do this.

So the question is not which framework is better. It is what structure stops, unlike work from competing—and which method you then use inside it.

RICE, WSJF, an impact-effort matrix, or capacity buckets with a simple score — which method survives contact with your stakeholders?

RICEWSJFImpact-effort matrixCapacity buckets + score
Setup costLow — four inputs per itemModerate — requires agreeing how to value delayLowest — a whiteboard and an afternoonModerate — the allocation negotiation is the work
Data requiredReach and impact estimates, confidence, effortCost of delay components and a duration estimateTwo rough judgements per itemWhatever the inner method needs, plus a capacity split
Handles time-sensitivityWeakly — a deadline is not an input, so dated work scores like undated workDirectly — it is the whole point; delay cost divided by durationNot at allYes, if cost of delay is the tiebreaker inside each bucket
Resists lobbyingModerate — until requesters learn which number to inflateModerate — arguing about delay cost is at least an argument about economicsWeak — two subjective axes and no audit trailStrongest — the allocation is agreed once, so a single request cannot consume the quarter
Transparency to stakeholdersGood — the arithmetic is explainableGood, once people accept the delay-cost framingExcellent as a picture, poor as a recordExcellent — people see both their share and the queue inside it
Gaming riskHigh — confidence and reach are the soft spotsModerate — inflating delay cost invites 'show the contract'High — it is two opinions in a gridLower — gaming one bucket does not take capacity from another
Fails whenEverything is high-confidence and high-reach, so scores clusterNobody can estimate delay cost and the exercise becomes theatreThe team is big enough that someone will later ask whyAllocations are set and never revisited, so they become folklore

When to pick each option

Use an impact-effort matrix when the team is small enough to fit around one table and the backlog is compact enough to read in a sitting. At that size, scoring frameworks are overhead, and two honest judgments plus a conversation usually give the same ordering. The message to graduates is political, not analytical: the first time somebody asks why their request was lost, you need a record.

Use RICE when you have multiple stakeholders and a backlog that no one can hold in their head. The real value is not in the arithmetic. It forces four separate questions that usually come fused into one opinion: how many people, how much per person, how sure are we, and how long will it take? Protect two inputs, or it degrades in a quarter. The effort is estimated by the people doing the work. Not the requester. Confidence must point to evidence. “High confidence” without any attachments is a preference for a number.

Use WSJF when deadlines and windows are really what drive value—regulatory dates, seasonal peaks, contractual commitments, and a competitive window. The only common method that gives small, time-critical work the advantage it deserves is dividing the cost of delay by its duration. The trap is that it needs an estimate of the cost of delay, and a team that cannot produce one will quietly invent numbers. If so, please keep the question and drop the formula. One of the advantages is to ask, “What is the cost of a week of delay?”

Once the team is running production systems with real customers, use capacity buckets with a score inside each—this is the recommendationdebt, and. Agree on the split with leadership once a quarter (for example, a majority to product work, a fixed share to reliability and debt, a visible reserve for unplanned escalations), then let RICE or WSJF rank inside each bucket. It is the only arrangement that stops an urgent request from consuming the quarter, because an escalation draws down its reserve rather than deleting the strategic work.

Recommended flow: classify first, score second, cap work in progress

Rendering diagram…

// Two ideas in forty lines: urgency is a number per week, and each class of
// work competes only against its own kind.

type WorkClass = 'interrupt' | 'commitment' | 'bet' | 'debt';

type Item = {
  title: string;
  workClass: WorkClass;
  reach: number;            // users or accounts affected per quarter
  impactPerUser: number;    // 0.25 minimal .. 3 massive
  confidence: number;       // 0.5 | 0.8 | 1.0 — must cite evidence, see below
  evidence?: string;        // no evidence, no confidence above 0.5
  effortWeeks: number;      // estimated by engineering, NEVER by the requester
  delayCostPerWeek?: number; // what a week of waiting costs, in money or risk
  deadline?: string;
};

function confidenceOf(item: Item) {
  // The single most-gamed input. Cap it when nobody can say why they are sure.
  return item.evidence ? item.confidence : Math.min(item.confidence, 0.5);
}

function score(item: Item) {
  const rice = (item.reach * item.impactPerUser * confidenceOf(item)) / item.effortWeeks;

  // Time-sensitivity enters as economics, not as adjectives. An item with a real
  // deadline and a real weekly cost outranks a bigger item that can wait.
  const wsjf = item.delayCostPerWeek ? item.delayCostPerWeek / item.effortWeeks : 0;

  return { rice, wsjf, combined: rice + wsjf };
}

// Rank WITHIN a class. Never across classes — that comparison is the bug.
function plan(items: Item[], capacityWeeks: number, allocation: Record<WorkClass, number>) {
  return Object.entries(allocation).map(([cls, share]) => {
    const budget = capacityWeeks * share;          // e.g. { bet: 0.5, debt: 0.2, ... }
    const queue = items
      .filter((i) => i.workClass === cls)
      .sort((a, b) => score(b).combined - score(a).combined);

    let spent = 0;
    const committed = queue.filter((i) => (spent += i.effortWeeks) <= budget);

    // The deferred list is the output that matters. Publish it.
    return { cls, budget, committed, deferred: queue.slice(committed.length) };
  });
}

// What this prevents: one escalation consuming the quarter. An interrupt draws
// down the interrupt reserve. When that reserve is empty, someone has to decide
// out loud what to drop — which is the conversation the whole system exists for.

MVP development planner

Scope, budget, and launch plan

Choose the product, platforms, and modules. The range, phases, and team update as you go. It is a planning figure, not a quote.

Product
Platforms
Modules
Design
Pace
Launch scale
Compliance

Newsletter

One architecture teardown or evaluation, every other week

Practical write-ups on framework choices, migrations, and scaling decisions—written for people who have to defend the call in meetings.

No spam. Unsubscribe anytime.

Newsletter

Get the 2026 Tech Stack Guide

Join the KarmaKoders newsletter for architecture notes, stack evaluations, and build playbooks.

No spam. Unsubscribe anytime.

Book a call WhatsApp