Progressive Enhancement in Modern SPAs

PerformanceArchitectureUX
Share on LinkedIn Share on X Share on Reddit Share on HN Share on Bluesky

The marketing team shipped a React-only contact form — when JS failed on a corporate proxy, leads dropped to zero until we added a native form action fallback.

Why this breaks in production

The marketing team shipped a React-only contact form — when JS failed on a corporate proxy, leads dropped to zero until we added a native form action fallback.

When: When reliability and accessibility matter more than cutting-edge-only APIs

Avoid: Assuming evergreen browsers means JavaScript is always available

How it works

Rehearse anti-pattern in design review: Assuming evergreen browsers means JavaScript is always available

Rollback via feature flag or cache purge must be documented in the PR before merge.

Implementation

Test refresh, back, double-submit, offline, and keyboard-only paths manually.

Failure modes

Third-party scripts change without your deploy — audit quarterly.

Global metric averages hide regional or device-class regressions.

Measurement

Slice dashboards by route, device, connection type, release version.

Alert week-over-week p75 regression on tier-1 surfaces.

Ship checklist

Link runbook from dashboard — not buried wiki.

Quarterly re-verify after browser releases and traffic shifts.

Reference implementation

performance.mark("start");
await applyChange();
performance.mark("end");
performance.measure("change", "start", "end");

When to prioritize

When reliability and accessibility matter more than cutting-edge-only apis.

Anti-pattern

Assuming evergreen browsers means JavaScript is always available.

Deep dive: rollout discipline (1)

The marketing team shipped a React-only contact form — when JS failed on a corporate proxy, leads dropped to zero until we added a native form action fallback. When rolling out changes to progressive enhancement with modern baseline browsers, compare canary p75 INP and LCP to control for a full business day in target regions before promoting to 100%. Document rollback in the PR: feature flag name, cache purge procedure, or revert commit — whichever restores prior behavior fastest at 2 a.m.

Slice metrics by device class and connection effective type. A fix helping desktop fiber but regressing mid-tier Android 4G should pause rollout, not ship globally.

Deep dive: failure rehearsal (2)

Rehearse Assuming evergreen browsers means JavaScript is always available in a 30-minute game day before peak season. For progressive enhancement with modern baseline browsers, measure time-to-detect and time-to-mitigate — not only time-to-root-cause in a postmortem doc.

Manual paths worth scripting: hard refresh mid-flow, browser back after async submit, double-click primary action, offline toggle during mutation, keyboard-only navigation with screen reader.

Deep dive: observability (3)

Wire custom RUM marks around the user journey progressive enhancement with modern baseline browsers affects. Log correlation IDs across client beacons and server logs. Alert on week-over-week p75 regression on tier-1 routes — global averages hide bad canaries.

Leading indicators: error rate, validation failures, queue depth. Lagging: support tickets, conversion, churn. Both must move together to confirm the fix matched user pain.

Deep dive: third-party drift (4)

Tag managers, chat widgets, and payment iframes change without your deploy. Quarterly audit script inventory on critical routes. Compare lab metrics with ad blockers enabled vs disabled — the delta reveals third-party cost.

For progressive enhancement with modern baseline browsers, corporate proxies and Save-Data alter behavior versus staging on office Wi-Fi. Field validation beats conference demos.

Deep dive: rollout discipline (5)

The marketing team shipped a React-only contact form — when JS failed on a corporate proxy, leads dropped to zero until we added a native form action fallback. When rolling out changes to progressive enhancement with modern baseline browsers, compare canary p75 INP and LCP to control for a full business day in target regions before promoting to 100%. Document rollback in the PR: feature flag name, cache purge procedure, or revert commit — whichever restores prior behavior fastest at 2 a.m.

Slice metrics by device class and connection effective type. A fix helping desktop fiber but regressing mid-tier Android 4G should pause rollout, not ship globally.

Deep dive: failure rehearsal (6)

Rehearse Assuming evergreen browsers means JavaScript is always available in a 30-minute game day before peak season. For progressive enhancement with modern baseline browsers, measure time-to-detect and time-to-mitigate — not only time-to-root-cause in a postmortem doc.

Manual paths worth scripting: hard refresh mid-flow, browser back after async submit, double-click primary action, offline toggle during mutation, keyboard-only navigation with screen reader.

Deep dive: observability (7)

Wire custom RUM marks around the user journey progressive enhancement with modern baseline browsers affects. Log correlation IDs across client beacons and server logs. Alert on week-over-week p75 regression on tier-1 routes — global averages hide bad canaries.

Leading indicators: error rate, validation failures, queue depth. Lagging: support tickets, conversion, churn. Both must move together to confirm the fix matched user pain.

Deep dive: third-party drift (8)

Tag managers, chat widgets, and payment iframes change without your deploy. Quarterly audit script inventory on critical routes. Compare lab metrics with ad blockers enabled vs disabled — the delta reveals third-party cost.

For progressive enhancement with modern baseline browsers, corporate proxies and Save-Data alter behavior versus staging on office Wi-Fi. Field validation beats conference demos.

Deep dive: rollout discipline (9)

The marketing team shipped a React-only contact form — when JS failed on a corporate proxy, leads dropped to zero until we added a native form action fallback. When rolling out changes to progressive enhancement with modern baseline browsers, compare canary p75 INP and LCP to control for a full business day in target regions before promoting to 100%. Document rollback in the PR: feature flag name, cache purge procedure, or revert commit — whichever restores prior behavior fastest at 2 a.m.

Slice metrics by device class and connection effective type. A fix helping desktop fiber but regressing mid-tier Android 4G should pause rollout, not ship globally.

Deep dive: failure rehearsal (10)

Rehearse Assuming evergreen browsers means JavaScript is always available in a 30-minute game day before peak season. For progressive enhancement with modern baseline browsers, measure time-to-detect and time-to-mitigate — not only time-to-root-cause in a postmortem doc.

Manual paths worth scripting: hard refresh mid-flow, browser back after async submit, double-click primary action, offline toggle during mutation, keyboard-only navigation with screen reader.

Deep dive: observability (11)

Wire custom RUM marks around the user journey progressive enhancement with modern baseline browsers affects. Log correlation IDs across client beacons and server logs. Alert on week-over-week p75 regression on tier-1 routes — global averages hide bad canaries.

Leading indicators: error rate, validation failures, queue depth. Lagging: support tickets, conversion, churn. Both must move together to confirm the fix matched user pain.

Deep dive: third-party drift (12)

Tag managers, chat widgets, and payment iframes change without your deploy. Quarterly audit script inventory on critical routes. Compare lab metrics with ad blockers enabled vs disabled — the delta reveals third-party cost.

For progressive enhancement with modern baseline browsers, corporate proxies and Save-Data alter behavior versus staging on office Wi-Fi. Field validation beats conference demos.

Deep dive: rollout discipline (13)

The marketing team shipped a React-only contact form — when JS failed on a corporate proxy, leads dropped to zero until we added a native form action fallback. When rolling out changes to progressive enhancement with modern baseline browsers, compare canary p75 INP and LCP to control for a full business day in target regions before promoting to 100%. Document rollback in the PR: feature flag name, cache purge procedure, or revert commit — whichever restores prior behavior fastest at 2 a.m.

Slice metrics by device class and connection effective type. A fix helping desktop fiber but regressing mid-tier Android 4G should pause rollout, not ship globally.

Frequently asked questions

Is progressive enhancement still relevant in 2026?

Yes. Ad blockers, CSP, corporate proxies, and low-end devices still break JS. Core actions — forms, navigation, content — should work without JS.

How does this interact with SSR frameworks?

SSR HTML is your enhanced baseline; hydration adds interactivity. Never render empty shells that require JS for primary content.

What is the modern baseline?

Target browsers with ES modules, CSS Grid, and fetch — enhance with View Transitions and Popover API where supported, not required.

Hiring a senior Android / Flutter engineer?

I architect and ship production mobile software — Kotlin, Jetpack Compose, Flutter — for robotics, EV infrastructure, fintech, and real-time systems. Open to remote roles in Europe and the US.

Get in touch →