Shopify shipped Hydrogen 2026.4.0 on April 17, 2026. Most of the release notes celebrate React Router 7.9.2 middleware support, Miniflare v3, and ten new Cookbook recipes. Fine — but buried in PRs #3649 and #3621 are three breaking changes that will throw runtime errors or silently break consent flows the moment you deploy an upgrade without reading them.
If you run a custom Hydrogen setup — any project that isn't a clean create-hydrogen skeleton — you need the migration guide before you push. This post is it: what changed, the exact code diffs, an audit checklist for your consent banner, and the import rewrites to unblock the upgrade today.
What Shipped in Hydrogen 2026.4.0
The Hydrogen April 2026 release landed the 2026.4.0 skeleton on April 17. At a glance:
- Storefront API and Customer Account API bumped to
2026-04 - React Router 7.9.2 with route module middleware and stronger typed route modules
- Miniflare v3 for local Oxygen parity
- 10 new Cookbook recipes covering B2B, metaobjects, infinite scroll, Partytown, GTM, markets, and more
- Three breaking changes that are the real story
The three breaking changes all touch the request pipeline or the consent layer. Here they are, in the order you should audit them.
Breaking Change #1: The Storefront API Proxy Is Now Mandatory
The proxyStandardRoutes option has been removed from createRequestHandler. The Storefront API proxy is always enabled in 2026.4.0. If your load context doesn't include a storefront instance at request time, the request handler throws — no warning, no fallback.
This was previously an opt-in convenience for the /api/* proxy routes. With 2026.4.0 it is a hard requirement, because backend consent mode (breaking change #2) writes consent cookies through that proxy. Shopify chose "loud failure over silent compliance breakage," and the missing-storefront warning has been promoted to a thrown error.
Who this affects:
- Any project with a custom
createRequestHandlercall that passedproxyStandardRoutes: false - Non-standard request handlers that construct a load context manually
- Multi-tenant or middleware-layered Hydrogen setups that may drop
storefronton some routes
The code diff:
// ❌ Before (2026.1 and earlier)import { createRequestHandler } from '@shopify/remix-oxygen';export default {async fetch(request, env, executionContext) {const handleRequest = createRequestHandler({build: remixBuild,mode: process.env.NODE_ENV,proxyStandardRoutes: false, // <— this option is gonegetLoadContext: () => ({ env, executionContext }),});return handleRequest(request);},};
// ✅ After (2026.4.0)import { createRequestHandler } from '@shopify/hydrogen';export default {async fetch(request, env, executionContext) {const storefront = createStorefrontClient({ /* ... */ });const handleRequest = createRequestHandler({build: remixBuild,mode: process.env.NODE_ENV,// proxyStandardRoutes removed — proxy always ongetLoadContext: () => ({env,executionContext,storefront, // <— now required or handler throws}),});return handleRequest(request);},};
Audit today:
- Grep your repo for
proxyStandardRoutes— delete every occurrence. - Confirm every code path that builds a load context includes a
storefrontinstance. - Test
/api/mcpand/api/sfapiroutes locally before deploying.
Breaking Change #2: Backend Consent Mode Is On by Default
Shopify is deprecating the legacy _tracking_consent JS-set cookie. Starting in 2026.4.0, Hydrogen sets window.Shopify.customerPrivacy.backendConsentEnabled = true before the Customer Privacy API script loads. The Customer Privacy API then switches to the new server-set cookie mode, writing consent through the Storefront API proxy instead of in the browser.
That is why the SF API proxy had to become mandatory first — the whole point of backend consent mode is that consent writes can't silently fail when a proxy is missing.
What breaks today if you don't audit:
- Custom consent banners that read
document.cookieand look for_tracking_consentwill see an empty value after upgrade - Cookie-consent analytics wrappers that wait for the legacy cookie before firing tags will stall silently
- GTM/Partytown setups that gate
dataLayer.pushon the legacy cookie will miss every conversion event
Consent banner audit checklist:
- Replace any
document.cookie.match(/_tracking_consent=/)checks withuseCustomerPrivacy()from@shopify/hydrogen - Confirm your banner calls
setTrackingConsent()rather than writing cookies directly - Verify
/api/consent(or equivalent SF API proxy path) responds 200 on a fresh session - Re-test GDPR, CCPA, and opt-out flows against the new server-set cookies
- For Partytown or GTM: confirm your consent gate reads from the
customerPrivacyAPI, notdocument.cookie
Shopify's Customer Privacy API team hardened getCustomerPrivacy() to check for setTrackingConsent before returning non-null, which prevents the pre-initialized config stub from being exposed as the usable API. Translation: if you used the stub on a stale Hydrogen version, that code silently short-circuits now. Good — but only if you caught it.
Breaking Change #3: @shopify/remix-oxygen Is Deprecated
The @shopify/remix-oxygen package is now deprecated. It was a legacy Remix adapter that re-exported 33 types and 10 runtime functions directly from React Router as a pass-through layer, plus its own createRequestHandler and getStorefrontHeaders — both of which now have better homes in @shopify/hydrogen and react-router directly.
The package still works and won't be removed in this release. But every export is marked @deprecated with JSDoc warnings, and new internal Hydrogen code imports from the replacements.
Exact import rewrites:
| Old import | New import |
|---|---|
import { createRequestHandler } from '@shopify/remix-oxygen' | import { createRequestHandler } from '@shopify/hydrogen' |
import { getStorefrontHeaders } from '@shopify/remix-oxygen' | import { getStorefrontHeaders } from '@shopify/hydrogen/oxygen' |
import type { LoaderFunctionArgs, ActionFunctionArgs } from '@shopify/remix-oxygen' | import type { LoaderFunctionArgs, ActionFunctionArgs } from 'react-router' |
import type { MetaFunction, LinksFunction } from '@shopify/remix-oxygen' | import type { MetaFunction, LinksFunction } from 'react-router' |
import { json, redirect } from '@shopify/remix-oxygen' | Use Response.json() and redirect from react-router |
Migration pattern — grep first, rewrite second:
# Find every usagegrep -rn "@shopify/remix-oxygen" app/# Rewrite imports (review diff before committing)find app/ -type f \( -name "*.ts" -o -name "*.tsx" \) -exec \sed -i '' \-e "s|from '@shopify/remix-oxygen'|from 'react-router'|g" \{} +
Then manually fix the two special cases — createRequestHandler (→ @shopify/hydrogen) and getStorefrontHeaders (→ @shopify/hydrogen/oxygen) — because they don't live in react-router.
The payoff: your Hydrogen app loses a circular build dependency (remix-oxygen had a devDep back on @shopify/hydrogen for the __H2O_LOG_EVENT global), ships fewer pass-through re-exports, and becomes standards-aligned with the broader React Router ecosystem.
Upgrade Path and the Weaverse Note
For most teams, the clean upgrade path is:
- Cut a branch:
git checkout -b upgrade/hydrogen-2026.4 - Run
npx shopify hydrogen upgrade— the CLI detects the release and applies codemods where possible - Grep for
proxyStandardRoutesand delete every occurrence - Grep for
@shopify/remix-oxygenand rewrite imports per the table above - Run your consent banner audit checklist
- Test
/api/mcp,/api/sfapi, and consent acceptance flows locally under Miniflare v3 - Deploy to a preview environment, verify analytics fire, then promote
If you run a Weaverse theme: Pilot is already on 2026.4 as of today. Naturelle and Maison ship their 2026.4 updates this week. If you've customized any request-handler or consent code on top of our themes, run the checklist before pulling the update.
If you're sitting on a heavily customized Hydrogen fork and this migration looks like a week of work you don't have — that's exactly what Weaverse themes exist to absorb. We track Shopify's release cadence so your merchants don't have to.



