skip to content

A feature's degraded path runs only when its generative step fails. How do you keep it exercised as the feature changes?

level: seniorimportance: should knowfreq 38%

answer

  1. No user visits it on a good day
  2. Exercised only if something forces failure
  3. Assert a positive outcome, not silence
  4. Change the primary view, revisit the fallback
  5. Count how often each fallback fires

basics

~20 s

Make the failure cases first-class: run them on every change rather than in an occasional batch, assert something positive instead of the absence of an error, review the fallback view whenever the primary view changes, and watch how often each fallback fires in production.

solid answer

~40 s

Nothing in ordinary use touches this path, so it stays alive only if something deliberately exercises it. Keep one case per delivery failure in the set that runs on every change, and make each assert a positive outcome — a named message, a working alternative, a delivered queued result — because a case asserting only "no error" passes long after the fallback stopped rendering. Review the fallback view whenever the primary view changes; a field added to one and not the other is the usual rot. Then watch production: count how often each fallback fires. Zero in six months means either the path is unreachable or the counter is broken, and both are worth knowing before a real outage makes it the first thing people see.

code

pseudocode · 18 lines
pseudocode
health checks on the degraded path:

on every change:
  run one case per delivery failure, not nightly only
  every case asserts a positive, specific outcome

on every change to the primary view:
  open the fallback view in the same review

weekly, from production:
  count fallback_shown grouped by failure kind
  alert when a kind that used to fire now never fires
  alert when abandonment after a fallback rises

rot signals:
  fallback text names a control that no longer exists
  manual route leads to a screen needing the failed step
  queued work written where nothing drains it

go deeper

for a junior

Understand that a path nothing exercises decays silently. If no person and no case ever makes the generative step fail, nobody finds out the fallback broke until a real outage. Knowing why it needs deliberate exercise is enough here.

for a middle

Explain what a useful assertion looks like on this path — specific and positive rather than the absence of an error — and why the fallback view has to be opened whenever the primary view changes.

for a senior

Bring the production side: counts per failure shape, what people do after seeing one, and the tells that the path rotted — text naming a removed control, an alternative route that needs the failed step, a queue nothing drains.

for a principal

Own how much upkeep a rarely-hit path earns. It competes with everything else for attention, and the honest positions are keeping it genuinely exercised or replacing it with one simple stop; leaving an unmaintained fallback in place and calling it handled is the option that is not defensible.

The degraded path has a property no other part of the feature has: on a good day nothing touches it. No user reaches it, no exploratory session reaches it, no demo shows it. It runs only when something deliberately makes the generative step fail, which in practice means it runs only if the team arranged for that. Everything about keeping it healthy follows from that one fact. ## Why it decays The feature around it keeps moving. The primary view gains a field, a control is renamed, a route is replaced, the product's vocabulary changes, the queue that used to drain the promised work is retired during a migration. None of those changes breaks a case nobody wrote, and none surfaces as an incident, because the path is invisible until the day the dependency actually fails — the worst possible moment to discover that the fallback text points at a button that no longer exists. There is a second, quieter decay: the case itself rots. A fallback case asserting "no error was thrown" or "the page loaded" keeps passing while the fallback panel renders empty. That is worse than having no case at all, because it occupies the slot a real case would take and reports green while doing it. ## Keeping it exercised - **One case per delivery failure, running on every change.** These cases are cheap — the failure is forced rather than reproduced — so there is no reason to exile them to an occasional scheduled batch where a break is found days later by nobody in particular. - **Positive, specific assertions.** Name the message. Follow the alternative control. Drain the queue and confirm the delivery. Every assertion should be one that fails if the fallback renders nothing. - **Pair the views in review.** Whenever the primary view changes, open the fallback view in the same change. A field added to one and not the other is the most common single cause of rot. - **Keep the fallback wording with the rest of the product's wording.** Text that lives off to the side is the text that survives a rename nobody applied to it. - **Count it in production.** How many times each failure shape was shown last week, and what people did next. ## The signs it has quietly rotted | Sign | What it usually means | | --- | --- | | The message names a control that no longer exists | The fallback was not revisited when the product moved | | The manual route leads to a screen that needs the failed step | The alternative stopped being an alternative | | Queued work is written where nothing drains it | The promise is now a lie no case checks | | Its case has been skipped or quarantined for months | The path is untested and everyone agreed not to notice | | The fallback has been shown zero times ever in production | Either the path is unreachable or the counter is broken | | The fallback is shown and people leave immediately after | It is technically present and practically useless | The last two are the ones only production can tell you. A count of zero is genuinely ambiguous and worth resolving, because it means either that these failures never happen — which deserves confirming against the dependency's own numbers — or that the path cannot be reached at all. ## When it is honest to remove it Not every degraded path is worth its upkeep. A rarely-hit route competes for attention with everything else, and there are two defensible positions: keep it genuinely exercised, or replace it with the simplest honest stop and delete the machinery behind it. What is not defensible is leaving an elaborate fallback in place, unexercised, and telling people it is there. If a queued promise cannot be maintained to the point where the delivery itself is asserted, a plain message saying the feature is unavailable is a better product than a promise nobody keeps. ## A quick audit 1. Force each delivery failure by hand once a quarter and look at the resulting screen with fresh eyes. 2. Read the fallback wording against the product's current vocabulary. 3. Follow every alternative route offered, to its end. 4. Check that each assertion would fail against an empty panel. 5. Compare production counts per failure shape against the dependency's own failure numbers.

  • What makes a fallback case rot even while it keeps passing?
    An assertion that cannot fail in practice. "No error was thrown" or "the page loaded" stays green when the fallback panel renders empty, when its message stops making sense, or when the alternative control leads nowhere. Replace it with an assertion that names the message and follows the alternative, so the case breaks on the day the path does.
  • How does production tell you a degraded path has quietly stopped working?
    By counting how often each failure shape is shown and what people do next. A shape that used to appear weekly and now never appears suggests the path or its counter is gone. A fallback that appears and is followed by immediate abandonment suggests it is technically present and practically useless.
  • Why is running these cases only in an occasional scheduled batch a false economy?
    Because a break is discovered days after the change that caused it, when several changes are candidates and nobody owns the result. These cases are cheap — the failure is forced rather than reproduced — so they belong beside the change that can break them, not in a batch people learn to skim.

saying these in an interview costs you the question

  • Runs the degraded cases only on an occasional schedule
  • Asserts that no error appeared and calls it covered
  • Updates the primary view and never opens the fallback
  • Assumes a path nobody reports broken is working
  • Deletes an unreliable degraded case instead of fixing it