Progressive Enhancement in Modern SPAs
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 →