Graceful Degradation

Concept

Building a product against the best available environment and then deciding what stays working — and what quietly falls away — when those conditions aren't met.

Why it exists

People don't all open a product under the same conditions. A three-year-old budget phone, a browser frozen by a corporate IT policy, and a connection that drops in a subway tunnel all load the same screen. The people building the product work on fast machines with fast connections, so that spread is invisible from the inside, and nothing in a normal day's testing surfaces it.

For years there were two ways of handling it. One was a page that said "your browser is not supported" and sent the visitor away. The other was to plan for nothing and let the screen break. Both share the same flaw: one optional feature failing takes the entire product down with it.

Pagedeck learned this the direct way. The day after Theo shipped live cursors — the colored markers showing where each collaborator is working in a document — a customer wrote in to say documents wouldn't open at all. The browser their staff used didn't support the capability the cursors were drawn with, and the failure there stopped the rest of the page from rendering. Reading and editing would have worked fine in that browser. A nice-to-have dragged every must-have down with it.

This approach treats that moment differently. It accepts up front that parts of the product may not run, and it decides at build time what has to survive when they don't.

How it works

Finish the product against the best environment, then work backward: strip each feature away in turn, decide what must remain, and write the code that fills that gap. Three steps.

  1. Pick the things the product cannot exist without. For a collaborative document tool that's opening a document, typing in it, and saving. Live cursors and emoji reactions are not on that list.
  2. Decide where you check the environment. Don't read the browser's name and version — ask directly whether the capability you need is present. Name-based checks lock out perfectly capable users every time a new browser appears that isn't on the list.
  3. Decide what ships instead when the capability is missing. Leave this blank and the screen stalls, because the code still tries to use something that isn't there.

The substitute usually takes one of three shapes. The first is hiding it quietly: in an environment that can't draw cursors, the cursors disappear and everything else stays. The second is falling back to a simpler version: if the drawing editor won't load, show the drawing as a flat image and hide the edit button. The third is explaining why something is unavailable, which is worth doing only when the person can act on the explanation. "Switch browsers and this works" helps; "something went wrong" is a wall, not a fallback.

A building whose elevator stops is still usable, because the stairs are there. A building with only an elevator is more pleasant most days and loses everything on the day it fails.

Where it shows up

On the front end, old browsers are the classic case. A polyfill can supply a missing capability in code, but not every capability can be filled that way, and the filler itself is heavy enough to hurt on slow devices. The decision to fold rather than fill gets made here.

The same principle runs on the server. In a microservices architecture, where features are split into separately deployed services, some part of the system is always down. Rather than letting a document list hang while it waits on the recommendations API, the list renders immediately with the recommendation strip left empty. An incident then takes out one panel instead of the whole product, and the team gets a few hours to fix it instead of a few minutes.

It also meets accessibility work, which aims at the same target from a different direction. A person running text at double size, or listening to the screen rather than looking at it, never receives the animation or the careful layout. The requirement that content and controls survive once those layers are peeled off is the same requirement this principle describes.

It differs from a feature flag in who decides. A flag is turned off by a person who judged the situation; degradation happens on its own, based on what the environment can do, at the moment it matters. The cases that belong here are exactly the ones that have to fold before anyone notices there was a problem.

How it sounds at work

"This doesn't run on older browsers — tell me what it should look like when it doesn't."

Implementation can't start until someone decides what ships in place of the feature.

"If recommendations time out, leave the strip empty and render the list."

One secondary element shouldn't hold up the content people came for.

"Instead of blocking them, let's show the parts that do work."

Cut down access rather than shutting it off, so that someone on an unsupported setup can still get the essential work done.

At Pagedeck this conversation attaches to design review. Noa posts a new screen, Theo asks what should appear where a given piece won't run, and Noa draws one more version of the screen in that state. Drawing the second version looks like overhead, but skipping it hands the decision to whoever implements the screen, and the usual result is an error state. What the customer sees then isn't a reduced product — it's a broken one.

What people get wrong

Removing features reads to some people as cutting corners, since it sounds like accepting less than the finished thing. It's closer to the opposite. Knowing what can be dropped requires deciding what the product actually is, and building the folded version of a screen is extra work, not less. Put the decision off and it gets made under pressure during an incident, where nobody picks the core — they switch off whatever is easiest to reach.

The other mistake is believing an error message satisfies the principle. The screen didn't break, a notice appeared, so it looks handled. But if the thing the person came to do is still blocked, the notice is a sign taped to a locked door. The test isn't whether a message rendered, it's whether the core action still runs. Miss that and the product accumulates dialogs, and users experience it not as a feature folding away but as a product that won't let them work.

Easily confused with

TermWhere it startsHow it differs
Progressive enhancementThe weakest environmentFinishes what works everywhere first and layers extras on top only where there's room. It settles what must be guaranteed up front, while graceful degradation settles what can be given up afterward

Where to go next

Last updated 2026-09-16