--- title: createRequestHandler description: >- Creates a request handler for Hydrogen apps. It wraps React Router's request handler and adds Hydrogen-specific functionality such as proxying Storefront API requests, collecting tracking information for analytics, and forwarding cookies to the browser. api_version: 2025-07 api_name: hydrogen source_url: html: 'https://shopify.dev/docs/api/hydrogen/latest/utilities/createrequesthandler' md: >- https://shopify.dev/docs/api/hydrogen/latest/utilities/createrequesthandler.md --- # create​Request​Handler Creates a request handler for Hydrogen apps. It wraps React Router's request handler and adds Hydrogen-specific functionality such as proxying Storefront API requests, collecting tracking information for analytics, and forwarding cookies to the browser. ## createRequestHandler(options) * build ServerBuild required React Router's server build * collectTrackingInformation boolean Default: true Collect tracking information from subrequests such as cookies and forward them to the browser. Disable this if you are not using Hydrogen's built-in analytics. * getLoadContext (request: Request) => unknown Function to provide the load context for each request. It must contain Hydrogen's storefront client instance for other Hydrogen utilities to work properly. * mode string React Router's mode * poweredByHeader boolean Default: true Whether to include the `powered-by` header in responses. * proxyStandardRoutes boolean Default: true Whether to proxy standard routes such as `/api/.../graphql.json` (Storefront API). You can disable this if you are handling these routes yourself. Ensure that the proxy works if you rely on Hydrogen's built-in behaviors such as analytics. Examples ### Examples * #### Example code ##### Description I am the default example ##### JavaScript ```js import {createHydrogenContext, createRequestHandler} from '@shopify/hydrogen'; import {createCookieSessionStorage} from 'react-router'; import * as reactRouterBuild from 'virtual:react-router/server-build'; export default { async fetch(request, env, executionContext) { const waitUntil = executionContext.waitUntil.bind(executionContext); const [cache, session] = await Promise.all([ caches.open('hydrogen'), AppSession.init(request, [env.SESSION_SECRET]), ]); /* Create context objects required to use Hydrogen with your credentials and options */ const hydrogenContext = createHydrogenContext({ env, request, cache, waitUntil, session, }); /** * Create a request handler with Hydrogen utilities. * This handler automatically proxies Storefront API requests * and collects tracking information for analytics. */ const handleRequest = createRequestHandler({ build: reactRouterBuild, mode: process.env.NODE_ENV, getLoadContext: () => hydrogenContext, }); const response = await handleRequest(request); if (session.isPending) { response.headers.set('Set-Cookie', await session.commit()); } return response; }, }; class AppSession { isPending = false; static async init(request, secrets) { const storage = createCookieSessionStorage({ cookie: { name: 'session', httpOnly: true, path: '/', sameSite: 'lax', secrets, }, }); const session = await storage.getSession(request.headers.get('Cookie')); return new this(storage, session); } get(key) { return this.session.get(key); } destroy() { return this.sessionStorage.destroySession(this.session); } flash(key, value) { this.session.flash(key, value); } unset(key) { this.isPending = true; this.session.unset(key); } set(key, value) { this.isPending = true; this.session.set(key, value); } commit() { this.isPending = false; return this.sessionStorage.commitSession(this.session); } } ``` ##### TypeScript ```ts import { createHydrogenContext, createRequestHandler, type HydrogenSession, } from '@shopify/hydrogen'; import { createCookieSessionStorage, type SessionStorage, type Session, } from 'react-router'; import * as reactRouterBuild from 'virtual:react-router/server-build'; export default { async fetch(request: Request, env: Env, executionContext: ExecutionContext) { const waitUntil = executionContext.waitUntil.bind(executionContext); const [cache, session] = await Promise.all([ caches.open('hydrogen'), AppSession.init(request, [env.SESSION_SECRET]), ]); /* Create context objects required to use Hydrogen with your credentials and options */ const hydrogenContext = createHydrogenContext({ env, request, cache, waitUntil, session, }); /** * Create a request handler with Hydrogen utilities. * This handler automatically proxies Storefront API requests * and collects tracking information for analytics. */ const handleRequest = createRequestHandler({ build: reactRouterBuild, mode: process.env.NODE_ENV, getLoadContext: () => hydrogenContext, }); const response = await handleRequest(request); if (session.isPending) { response.headers.set('Set-Cookie', await session.commit()); } return response; }, }; class AppSession implements HydrogenSession { public isPending = false; constructor( private sessionStorage: SessionStorage, private session: Session, ) {} static async init(request: Request, secrets: string[]) { const storage = createCookieSessionStorage({ cookie: { name: 'session', httpOnly: true, path: '/', sameSite: 'lax', secrets, }, }); const session = await storage.getSession(request.headers.get('Cookie')); return new this(storage, session); } get(key: string) { return this.session.get(key); } destroy() { return this.sessionStorage.destroySession(this.session); } flash(key: string, value: any) { this.session.flash(key, value); } unset(key: string) { this.isPending = true; this.session.unset(key); } set(key: string, value: any) { this.isPending = true; this.session.set(key, value); } commit() { this.isPending = false; return this.sessionStorage.commitSession(this.session); } } ``` ## Related [- createHydrogenContext](https://shopify.dev/docs/api/hydrogen/utilities/createhydrogencontext) [- createStorefrontClient](https://shopify.dev/docs/api/hydrogen/utilities/createstorefrontclient)