Reference

Hydrogen or a Bespoke Xano + Cloudflare Stack

For: Teams choosing between Shopify Hydrogen on Oxygen and a bespoke Xano + Cloudflare commerce stack Updated: 2026-10-29 · Hydrogen: 2026-10 · Shopify CLI: 5.0.0


Short answer

They aren't substitutes. Hydrogen replaces only the storefront layer. Pick it when a client wants a standard Shopify storefront with Shopify-managed hosting. Keep the bespoke stack as the core when data comes from more than Shopify, when one backend serves several brands or regions, or when consent and data residency must be enforced in code you control.

Headless only, or CMS-agnostic

Hydrogen and Next.js can only be headless with Shopify. They replace the Online Store theme and run beside Shopify, so a store that adopts them leaves the theme editor and its theme apps behind.

Webflow, Xano and Cloudflare are CMS-agnostic. The same worker, data layer and web components serve WordPress, Shopify, AEM and Next.js, Astro, Svelte or Vue front ends, and Webflow's CMS can itself act as a headless content source. Each can run headless, or be brought into a Shopify native theme through a theme app extension, so the store keeps its theme editor and checkout.

App blocks need an Online Store 2.0 theme with JSON templates; app embeds work in vintage themes too. Shopify suggests keeping each block's own JavaScript under 10 KB compressed, so the block loads a small loader from the worker, as the CRM Sync Brand Kit extension does.

Request path

Hydrogen + Oxygen

  1. Browser: Hydrated React app
  2. Oxygen worker: React Router renders each page on the server
  3. Storefront API + Customer Account API: Products, cart, checkout, customer accounts
  4. Shopify: The only source of truth

Bespoke Xano + Cloudflare

  1. Browser: Webflow or 11ty pages, enhanced with small scripts or web components
  2. Cloudflare Worker: Consent gate, routing per tenant, auth, cart and checkout calls
  3. Xano: Source of truth for product info (PIM), customers (CRM) and consent records
  4. Shopify, Webflow CMS, drop-ship suppliers: Feed Xano through webhooks and sync jobs; assets live in R2

The Hydrogen CLI got smaller

In 2026-10 the Hydrogen CLI only handles the Shopify platform. You build, run and generate code with React Router's own tooling. Shopify CLI @shopify/cli-hydrogen 13.0.1 and later stops the old commands with an error.

Still in the Hydrogen CLI

2026-04 and earlier only

Projects that run npm run dev --codegen are on 2026-04 or earlier and need Shopify's migration guide to move to 2026-10. hydrogen init still creates a 2026-04 project.

Comparison

ConcernHydrogen + OxygenBespoke Xano + CloudflareEdge
ScopeOne storefront: pages, cart, customer accountsBackend, PIM, CRM, consent, webhooks, agent checkout, several front endsBespoke
Source of truthShopifyXano; Shopify is one inputDepends
Rendering modelHeadless only, like Next.js on Shopify; the Online Store theme is replacedCMS-agnostic: WordPress, Shopify, AEM, Next.js, Astro, Svelte, Vue, either headless or inside a Shopify theme through app blocks and app embedsBespoke
Front endReact, rendered on the serverAny: Webflow, 11ty, UIkit with petite-vue, no React requiredBespoke
HostingOxygen, run by Shopify, included with the planWorkers, KV, R2 on your Cloudflare accountHydrogen
Data residencyOxygen decides; little regional controlYou choose regions, including a Xano instance in the visitor's countryBespoke
ConsentCustomer Privacy API is built in, but every page renders on the server before the visitor's choice is knownA gate in the worker decides what leaves, per region and per tenantBespoke
Brands and regionsOne Hydrogen app per storefrontOne worker serves many tenants from configBespoke
Non-Shopify dataPossible, but you fetch and cache it yourselfNative: CMS, drop-ship feeds, asset storesBespoke
Cart and checkoutFirst-class, kept current by ShopifyYou call the Storefront API and keep up with its versionsHydrogen
UpkeepShopify handles deploys, scaling, API upgradesYou own token refresh, webhook queues, deploys, monitoringHydrogen
Time to first launchFast for a standard storefrontSlower to stand up; reused across projects afterwardsHydrogen
SAP, Salesforce, Merchant CenterAttach to Shopify through apps and middleware; the storefront isn't involvedAttach to Xano and the worker, behind the same consent gateDepends
Sign-inShopify customer accounts (OIDC) built in, for one storeOne /auth/me across Google, Shopify and Kakao identities and every tenantDepends
Agent checkout (UCP)Shopify publishes the store's UCP profile and runs checkout; AP2 mandates aren't part of its documented flowYou verify AP2 mandates and set limits per agentDepends
Kakao Pay, Samsung PayOnly through a Shopify-approved payments appDirect PG or Stripe integration in the workerBespoke
Native appsA separate iOS or Android app using Checkout Kit and the Storefront API; no desktop shellTauri shells wrap the same web app, with one Rust core shared by native and webBespoke
Wallet passesThrough loyalty apps from the App StoreGoogle Wallet, Samsung Wallet and KakaoTalk passes built from your own ledgerBespoke
App and game distributionSeparate native app per store; no game pathOne PWA across web, stores, Galaxy Store and games, with Shopify as the security layerBespoke
3D and STL printingGLB and USDZ product media, public on Shopify's CDN; no STLPIM Sync for 3D files, three.js customizer, STL export, domain-locked loadingBespoke
PermissionsAccess scopes per app and resourceCaps per peer and direction, from /auth/me, enforced in the worker and an Axum serviceBespoke
Skills neededReact, React Router, GraphQLWorkers, XanoScript, GraphQL, the CMS of choiceEven

Integrating SAP, Google Merchant Center and Salesforce

With Hydrogen, these systems connect to Shopify, not to the storefront. Hydrogen only shows whatever has already reached Shopify. In the bespoke stack they connect to Xano and the worker, so the same consent and residency rules cover them.

SAP

S/4HANA, ECC, Business One · Edge: Bespoke

Hydrogen + Oxygen

Connects through. Middleware between the Shopify Admin API and SAP: SAP Integration Suite, or an iPaaS such as Boomi or Celigo.

What syncs. Material master to products, stock levels to inventory, orders and fulfilment back to SAP.

Watch for. Shopify becomes a second product master. SAP fields with no Shopify equivalent end up in metafields.

Bespoke Xano + Cloudflare

Connects through. The worker or Xano calls S/4HANA OData APIs. Integration Suite relays IDocs, and S/4HANA business events arrive through Event Mesh, both posting to a worker endpoint and a Cloudflare Queue.

What syncs. SAP stays master for material, price and stock. Xano adds copy, media and translations, keyed by material number, and pushes the result to Shopify.

Watch for. You own retries, field mapping and SAP authentication (OAuth or client certificates).

Google Merchant Center

Shopping ads, free listings, agentic checkout · Edge: Depends

Hydrogen + Oxygen

Connects through. Shopify's Google & YouTube app, which syncs the Shopify catalog to Merchant Center.

What syncs. Products, prices and availability, with a feed for each Shopify Market.

Watch for. Product links must point to the Hydrogen domain, and product pages need structured data that matches the feed, or items are disapproved. Titles and attributes can only be adjusted through metafield mapping.

Bespoke Xano + Cloudflare

Connects through. Merchant API, which replaces the Content API for Shopping. Xano or a scheduled worker inserts products for each feed label and language, or Merchant Center fetches a scheduled feed file from R2.

What syncs. Price, sale price and sale dates for each market, so prior-price rules such as Omnibus match what Google shows.

Watch for. Account and data source setup, API quotas, and keeping the landing-page price identical to the feed price.

Salesforce

Sales, Service and Marketing Cloud, Data 360 · Edge: Bespoke

Hydrogen + Oxygen

Connects through. A Shopify-to-Salesforce connector app or MuleSoft, with Shopify Flow and webhooks for events. MuleSoft's Shopify connector is built on Shopify's REST Admin API, which Shopify made legacy on 1 October 2024. Since 1 April 2025 new public apps must use the GraphQL Admin API, and Shopify began switching off REST endpoints in October 2025. Products with more than 100 variants (the limit became 2,048 on 15 October 2025), metaobjects and newer Markets features are GraphQL-only, so the connector can't reach them. Use MuleSoft's HTTP connector with the GraphQL Admin API for new work.

What syncs. Customers, orders and email and SMS marketing consent. Customers sign in through the Customer Account API, so Salesforce sees them only after Shopify does.

Watch for. Shopify records consent per channel. It has no field for consent by purpose or by region.

Bespoke Xano + Cloudflare

Connects through. Salesforce REST and Bulk API 2.0 from the worker, through a connected app using the OAuth client-credentials flow. Changes come back as Flow HTTP callouts to a worker endpoint. The Data 360 (formerly Data Cloud) Ingestion API takes behaviour events.

What syncs. Xano customer and consent records map to Salesforce's consent objects (Individual, Contact Point Type Consent).

Watch for. The Pub/Sub API needs gRPC, which Workers can't run as a client, so use Flow callouts or CometD streaming for change events.

What GraphQL and Merchant API require of CRM and ERP data

Shopify's GraphQL Admin API and Google's Merchant API each fix the shape a product, price, customer or order must arrive in. That shape flows back as requirements on SAP, Salesforce and the PIM. Both stacks face the same requirements; the difference is where the mapping lives. With Hydrogen it sits in connector apps or middleware. In the bespoke stack it sits in Xano, once, and feeds every peer.

The deprecation calendar

Why SAP S/4HANA and the Merchant feed feel it first

A Google feed reads the catalogue from Shopify and writes it to Merchant Center, so it sits on both migrations at once: Shopify REST to GraphQL on the read side, Content API to Merchant API on the write side. A feed can't push a catalogue it can no longer read. SAP integrations built on REST connectors hit the same wall, and SAP's OData shape (materials, plants, condition records) matches neither GraphQL nor Merchant API.

Xano as the conversion layer

Xano keeps one canonical record per product, price, customer and order. Adapters translate in each direction: SAP OData into the canonical record, the canonical record out to Shopify GraphQL bulk mutations and to Merchant API inputs in micros per feed label. Older systems and MuleSoft flows keep calling Xano's REST endpoints unchanged while Xano speaks GraphQL to Shopify. When Shopify or Google ships a breaking version, one adapter is amended instead of every connected system. Token refresh moves into the same layer: Xano and the worker renew expiring Shopify tokens per store, so SAP, MuleSoft and feed tools never hold a Shopify token that can lapse.

DataShopify GraphQLGoogle Merchant APIWhat CRM and ERP must supply
Product identityGlobal IDs such as gid://shopify/ProductVariant/…One product per contentLanguage~feedLabel~offerId, for example en~US~SKU123One stable SKU per variant, and a crosswalk from SAP material number to Shopify ID, Merchant offer ID and Salesforce product
VariantsOptions and up to 2,048 variants per product; REST tools break above 100One item per variant, grouped by item group IDOption values as separate fields (size, colour, fabric), never inside the title
PriceDecimal amount and currency; prices per market through Markets cataloguesInteger amountMicros and currencyCode, sale price with start and end dates, per feed labelA price per market and currency, sale windows with dates, and the prior price each market's rules need, such as Omnibus in the EU
IdentifiersBarcode field on the variantGTIN, brand and MPN, or a declaration that none existGTIN, brand and manufacturer part number held in the PIM, not typed in at listing time
LanguageTranslations per locale through the Translations APIContent language fixed per product or data sourceTranslated title and description per language, with a source of truth for each
StockInventory quantity per locationAvailability as a fixed value (in stock, out of stock, preorder), optionally per regionStock by warehouse, mapped to the countries each warehouse serves
Custom dataMetafields and metaobjects, GraphQL onlyDefined product attributesTyped attributes with definitions, not free-text notes
Customers and consentCustomer ID with email and SMS marketing consent: state, opt-in level and the time it changedNo customer dataConsent per channel with timestamp and opt-in level, kept in step with Salesforce's consent objects
Orders and moneyEach amount in both shop currency and the currency the customer paid inNo order dataERP postings that keep both currencies and the exchange rate used
Sync mechanicsCursor pagination, bulk exports as JSONL files, rate limits by query cost, webhooksProduct inserts processed after a delay of minutes; batching by parallel requestsQueue-based, idempotent and resumable jobs, never page-by-page REST loops

Upstream blockers when the ERP feed is REST-shaped

Sign-in, UCP mandates and Korean wallets

Hydrogen handles these through Shopify, so what it can do is whatever Shopify offers. In the bespoke stack, the worker connects each provider directly and stores the result in Xano under one user.

Sign-in and Auth Me

Google, Shopify customer accounts (OIDC), Kakao Login · Edge: Depends

Hydrogen + Oxygen

Connects through. The Customer Account API, an OAuth 2.0 and OpenID Connect flow with PKCE. Hydrogen's customerAccount helper handles login, callback and logout.

Google and other providers. Limited to the sign-in options Shopify customer accounts offer. Shopify Plus stores can connect an external identity provider; Multipass works only with legacy accounts.

Watch for. The session belongs to one store. A second brand or region means a second login.

Bespoke Xano + Cloudflare

Connects through. The worker runs each OIDC flow: Google Identity Services, the Shopify Customer Account API (discovered from the shop's /.well-known/openid-configuration) and Kakao Login. It checks each ID token against the provider's keys, then Xano issues its own token.

What Auth Me returns. One user with the claims from each linked identity, the extras stored for that user, and their capability caps, the same for every tenant.

Watch for. Link accounts only on a verified email or an explicit link step, never on an unverified email match.

GET /auth/me
{
  "logged_in": true,
  "user": { "id": 4182, "email": "…" },
  "claims": { "google_sub": "…", "shopify_customer_gid": "…" },
  "extras": { "region": "KR" },
  "entitlement": { "caps": ["checkout", "agent:delegate", "syndicate:out:webflow"] }
}

Example response; field names are illustrative.

Agent checkout with UCP

Universal Commerce Protocol with AP2 mandates · Edge: Depends

Hydrogen + Oxygen

Connects through. Shopify publishes the store's UCP profile at /.well-known/ucp and runs checkout, so agents can buy from it. The merchant stays the merchant of record. Hydrogen isn't in that path.

Mandates. AP2 mandates are an optional UCP extension that the business verifies. Shopify's agent checkout docs don't cover them.

Watch for. You work within the checkout Shopify exposes. Custom limits per agent or per customer aren't part of it, and agents only see the Shopify catalog.

Bespoke Xano + Cloudflare

Connects through. The worker publishes the UCP business profile at /.well-known/ucp, advertises the AP2 mandates extension, checks each mandate's signature, then creates the Shopify checkout or order.

Mandates. Stored in Xano against the user and the agent. The intent mandate's limits (amount, merchant, expiry) become capability caps the worker enforces.

Watch for. You maintain the spec version, key rotation and an audit trail that can show what each agent was allowed to do.

Kakao Pay and Samsung Pay

Korean wallets for a Korea-to-US storefront · Edge: Bespoke

Hydrogen + Oxygen

Connects through. Shopify Checkout only, so Hydrogen can't add a payment method of its own. A Korean wallet has to come from a payments app. The Shopify App Store lists Toss Payments and a third-party KakaoPay Checkout app; confirm each one runs inside checkout rather than redirecting off-site.

What syncs. The order and payment stay inside Shopify; the provider settles with the merchant.

Watch for. Shopify Payments isn't offered in Korea, and Samsung Pay isn't a built-in wallet the way Apple Pay, Google Pay and Shop Pay are.

Bespoke Xano + Cloudflare

Connects through. Kakao Pay's own API from the worker, with secret-key auth: a ready call returns the payment ID and redirects for app, mobile and desktop, then an approve call confirms it with the returned pg_token. Alternatively, a Korean PG such as KG Inicis or NHN KCP, which covers both Kakao Pay and Samsung Pay, or Stripe's Korean payment methods.

What syncs. After payment, the worker creates the Shopify order with the transaction marked as paid through an external gateway, so fulfilment and reporting stay in Shopify.

Watch for. Stripe's Korean methods charge in KRW, to customers in Korea, and need a merchant based in the US, UK, Japan, Hong Kong, Singapore or the EEA, not Korea. PIPA restricts sending Korean personal data abroad, so keeping it in a Seoul-region Xano instance is the simpler policy. Test the app-to-app redirect on mobile.

Apps, games, wallets, 3D and permissions

The bespoke stack ships the same web front end as a website, an installable app, a desktop app and a TV app, with a shared Rust core inside each, and Shopify stays the security layer behind all of them. Its wallet support covers two separate jobs: paying with a wallet and holding a pass in one. 3D models and print files travel through PIM Sync, and every permission is scoped by the direction the data moves. Reference builds: the Ondol Life site and thermostat app, and the fo1 Korea storefront, which runs Kakao Pay checkout in test mode.

Native app capability

Desktop, mobile and TV from one front end · Edge: Bespoke

Hydrogen + Oxygen

Connects through. A separate native app. Shopify's Checkout Kit shows Shopify Checkout inside an iOS, Android or React Native app, and the app reads products from the Storefront API.

Shared code. None with the Hydrogen site. Logic such as pricing rules or calculators is rewritten in the app, or called from a server.

Watch for. No desktop or TV shell, and two codebases to keep in step.

Bespoke Xano + Cloudflare

Connects through. Tauri 2 wraps the existing web app in a Rust host with the system webview. The same front end also ships as an installable web app and as a Samsung or LG TV app.

Shared code. A Rust core crate holds the calculations. Tauri links it natively, and the website loads the same crate compiled to WebAssembly, so the app and the page can't give different answers.

Capabilities. Tauri denies native access unless a capability file grants it, per window. When the app loads remote content, list that domain and grant it only what it needs, for example opening links in the system browser.

Watch for. App store signing and review, and pinning the WebAssembly tooling to the exact version the core was built with. Keep commerce out of safety logic: a purchase can unlock a feature, never change a device limit.

Hybrid wallet capability

Paying with a wallet, and holding a pass in one · Edge: Bespoke

The same brands sit on both sides, with different APIs: Google Pay pays and Google Wallet holds; Samsung Pay pays and Samsung Wallet holds; Kakao Pay pays and a KakaoTalk membership holds.

Hydrogen + Oxygen

Paying. The wallets Shopify Checkout offers: Shop Pay, Apple Pay and Google Pay. Other wallets need a payments app.

Holding passes. A loyalty app from the App Store issues the cards, from that app's own points data.

Watch for. Points live in the loyalty app, so a pass can't be checked against your own records.

Bespoke Xano + Cloudflare

Paying. Two kinds of rail. Agent rails (UCP, MPP, Kakao Pay) need an AP2 mandate. Wallets a person approves at the payment sheet (Google Pay, Apple Pay, Samsung Pay) need no mandate. A per-market settlement gate picks cross-border Stripe or a domestic PG, and blocks a rail a market doesn't allow.

Holding passes. One programme in Xano, published as a Google Wallet loyalty card, a Samsung Wallet card or a KakaoTalk membership. Balances fold from an append-only points ledger. Warranty passes work the same way from a service ledger.

Keeping passes honest. Each card records the ledger position it was built from. A card is out of date when the ledger has moved past that position, even if the balance looks the same, because an equal earn and spend leave the number unchanged.

Watch for. Each wallet provider has its own issuer approval, class rules and review. Warranty passes also go out of date as time passes, with no ledger event.

App and game distribution

PWA, app stores, Galaxy Store, Roblox and Unity, with Shopify as the security layer · Edge: Bespoke

Hydrogen + Oxygen

Distribution. The Hydrogen site can be made installable by hand. App store presence means a separate native app with Checkout Kit. Games have no path except calling the Storefront API from the game engine.

Security layer. Shopify handles sign-in, checkout and card data, for that one storefront.

Watch for. Each new surface is a new build with its own login.

Bespoke Xano + Cloudflare

Distribution. One progressive web app, shared by URL, listed in Galaxy Store as a PWA, and wrapped for the Apple and Google stores with Despia or Tauri. Roblox and Unity games link the player ID to the same Xano user.

Security layer. Shopify stays underneath every surface: customer accounts for identity, Shopify Checkout and tokenized wallets for payment, so no app or game ever handles card data. The worker checks caps and mandates before anything reaches Shopify.

Watch for. Digital goods sold inside an app store or game fall under that platform's billing; physical goods can go through web checkout. Game platforms add an age gate and children's privacy rules.

3D customizer, PIM 3D and STL printing

Configure in 3D, sync models and print files, load them securely · Edge: Bespoke

Hydrogen + Oxygen

3D on the product page. Shopify product media accepts 3D models as GLB or USDZ, shown with Hydrogen's ModelViewer and in AR on phones. STL isn't accepted as product media.

Customizer. A third-party app draws the configurator; the chosen options ride on the order as line item properties.

Watch for. Files on Shopify's CDN are public to anyone with the link, and print files need storage outside product media.

Bespoke Xano + Cloudflare

3D PIM Sync. Xano holds each product's 3D files (GLB, USDZ, STL, OBJ) with a mirrored copy in R2. PIM Sync pushes GLB and USDZ to Shopify's 3D media, and model and print-file links to Webflow CMS.

Customizer. A three.js configurator rebuilds the model from the chosen pieces, sizes and fabric, and sends that configuration with the quote. A swatch photo the customer uploads stays in their browser.

STL printing. The same scene exports to STL with three.js, for scale models, sample parts and hardware. Use 3MF when the printer needs units or colour. Mesh checks (watertight, wall thickness, scale) can sit in the shared Rust core, so the website and the app reject the same files.

Secure model loading. R2 only serves allowlisted storefront domains, its bucket can't be listed, and Cloudflare's firewall applies. The STL viewer runs in a sandboxed iframe on its own origin and loads files from R2 there, so the host page never fetches them. Uploads are signed on the server.

Watch for. STL carries no units or colour, so fix millimetres in the export. A copy pushed to Shopify becomes public.

Permissions by direction

Inbound and outbound syndication with peers, on Tokio and Axum, from Auth Me claims and extras · Edge: Bespoke

Hydrogen + Oxygen

Permissions. Each app gets Shopify access scopes per resource (read or write products, orders, customers). Channels that syndicate products to peers each install with their own scopes.

Watch for. Scopes say what an app may touch, not which way data may move. A channel with product write access can also overwrite what came in from elsewhere.

Bespoke Xano + Cloudflare

Direction. Every flow is inbound (consent, customers, orders coming in) or outbound (products, prices and media syndicated to peers such as Shopify, Webflow, Merchant Center and SAP). A cap grants one direction for one peer; outbound product rights never let a peer write consent or customers back.

Auth Me claims and extras. /auth/me returns the user, the claims from their linked Google and Shopify identities, the extras stored for them, and their entitlement caps. The worker gates on the caps; the page only uses them to hide controls.

Tokio and Axum. A Rust service on Tokio and Axum fronts Xano, SAP and Dataverse. It forwards only listed routes and methods, never caches signed-in requests, never forwards DELETE, and keeps SAP and Dataverse server-only behind a key that browsers can't send. It runs in Cloudflare Containers.

Watch for. Keep event records append-only and direction rules one-way: a suppressed contact stays suppressed, and consent is never back-filled.

Route list for the Axum service
GET  products/*        # outbound: peers read the catalogue
POST consent           # inbound: records a choice
PATCH sap:A_Product/*  # outbound to SAP, server-only

Example entries; route names are illustrative.

Where the payment gate runs: Worker or Axum

Who may pay with Kakao Pay is application code, not the runtime

Neither runtime decides who may pay with what. Tokio schedules tasks across a pool of threads, and Rust's ownership rules are checked when the code compiles. A Cloudflare Worker runs each request in its own V8 isolate. Both keep one request's memory away from another's, but a rule such as "Korean market plus the settle_sovereign_kr entitlement unlocks Kakao Pay" is code you write. It should gate on the market the purchase settles in and an entitlement cap, never on nationality.

StepWhereWhat it does
1. Verify the callerWorkerChecks the token on the server and loads the caller's caps
2. Look up the marketXano settlement policy and country gateway tableReturns the market's gateway, whether it is sovereign, and the cap it requires
3. DecideWorker settlement gateRefuses blocked, preview and sanctioned markets; returns 403 when a sovereign market's cap is missing
4. SettleWorker, calling Kakao PayRuns ready and approve only after step 3 passes

Why the Worker. Every request already passes through it, so the rule sits beside the consent, tenant and mandate checks it depends on, and a refusal happens before anything reaches Xano, Shopify or Kakao. The request's cf.country is a useful signal, but it is where the IP address appears to be, not the market of settlement.

Where Axum fits. A second check behind the Worker for server-only routes such as SAP and Dataverse writes. If it ever takes payment routes, it verifies the token and caps itself instead of trusting the Worker's result.

Rust at the edge. The gate doesn't need Axum to be written in Rust: workers-rs compiles Rust to WebAssembly and runs it as a Worker, the same pattern as the shared Rust core in the Tauri apps.

Isolation by region. Keeping Korean personal data in Korea is a deployment choice, a Seoul-region service beside a Seoul Xano instance, not something a thread scheduler or memory manager does.

// Axum middleware: fail closed unless the market and cap match
let allowed = caller.market == "KR"
    && caller.caps.iter().any(|c| c == "settle_sovereign_kr");
if !allowed { return Err(StatusCode::FORBIDDEN); }

Certificates, PKI tokens and the data release

The security layer under edge-served data and privacy cookies, after the eMudhra CA compromise

Certificates prove who is on each end of a connection. The release gate decides whether data may leave, to whom and when. TLS proves the connection, not the bytes, so a valid certificate never unlocks data by itself.

StepCertificate's roleWhat decides
0. Inbound connectionThe TLS server certificate proves the visitor reached the real domain. CAA DNS records limit which CAs may issue it.Nothing is released
1. Who is callingPeople present tokens. Machines such as a POS or SAP can present a client certificate (mutual TLS), which proves which machine; the Worker maps it to caps.Identity only
2. Agent mandatesAP2 mandates are signed credentials checked against the issuer's published keys.The caps and limits inside the mandate
3. Release decisionNone. The Worker gate and the Xano release gate check consent at the system of record, market, caps and residency, fail closed and write the release ledger.This is the release
4. Outbound callCertificates prove the destination: public TLS to Google and Shopify, a client certificate to SAP, Samsung Pay's encrypted token, Apple Pay's merchant certificate at Stripe.Delivery of data already approved
5. AuditThe ledger records which key or certificate fingerprint signed or carried each release.Evidence, not a decision

What is a PKI token

A PKI token is a credential whose authority comes from a private key, checked against the matching public key or certificate. It has two common forms. A hardware PKI token is a USB key or smart card that holds a private key and its certificate; the key never leaves the device, which is how India's digital signature certificates are issued. A software PKI token is a signed token (JWS, or an encrypted JWE) that anyone can verify against a published key set without calling the issuer.

Permissions it carries. Audience, scope or caps, market, and the subject it acts for, all inside the signature, so a holder can't widen them. The release gate still checks them against the system of record.

History restrictions. Limits in time and use: not-before and expiry; a unique ID so each token or mandate is used once or a set number of times, recorded in the ledger; revocation (a denylist for tokens, CRL or OCSP for certificates); and a read window, so a token reaches only records created after the subject's consent and inside the retention period, never back-filled history.

Key rotation. Signing keys move from next to active to retired. Tokens and certificates signed by a retired key still verify until they expire, and a compromised key is revoked instead of retired.

The eMudhra gap

In October 2026 a researcher showed that the private keys of eight eMudhra intermediate CAs could be recovered from their public certificates. Browsers blocked them within days, and Chrome removed the emSign ECC Root CA - G3 from its root store on 27 October 2026. Every site and client that trusted that chain had to replace certificates or patch trust stores, including Node, Python's certifi and Go. The lesson for edge-served data: TLS trust is rented from public CAs, and a CA failure breaks the layer that Secure cookies and edge delivery depend on.

Cookie flagWhat it stopsDepends on the CA chain
SecureSending the cookie over plain HTTPYes: a forged certificate lets an interceptor read it
HttpOnlyScript on the page reading the cookieNo
SameSiteSending the cookie on cross-site requestsNo
__Host- prefixSubdomains setting or overriding the cookie; requires Secure, no Domain and Path=/Yes
PartitionedA third-party cookie following the visitor across sitesNo

What closes the gap. CAA records with an incident contact, so only chosen CAs can issue; Certificate Transparency monitoring for unexpected certificates; patched trust stores in every server-side client, not only browsers; and consent kept as a signed server-side record, so a stolen or forged cookie can't rewrite what a visitor agreed to.

Bring your own CA. Device and code-signing certificates from a CA the business operates or chooses, with only the signing request leaving its network.

A visitor's first page load

The difference shows up before the visitor has said yes or no. Steps marked in pink are where data can leave without a decision; steps marked in blue are where the stack checks one.

Hydrogen + Oxygen

  1. The request reaches Oxygen with its headers, IP and cookies.
  2. The server renders the page and calls any APIs the route needs, including third-party ones.
  3. HTML and the React bundle reach the browser.
  4. The consent banner appears and the Customer Privacy API records the choice.
  5. Analytics respect the choice from here on. Anything the server sent in step 2 already happened.

Bespoke Xano + Cloudflare

  1. The browser loads static HTML from the edge; no personal data is used to build it.
  2. The consent banner records the choice for the visitor's region.
  3. The worker's gate checks that choice before forwarding anything to Xano, Shopify or analytics.
  4. Data goes only to regions the tenant allows.
  5. Scripts that personalise the page load after consent.

Hydrogen can be made consent-safe, but that is an audit you repeat for every route. In the bespoke stack the gate is in one place and applies to every route.

When to pick which

Choose Hydrogen when

Choose the bespoke stack when

Hydrogen on top of Xano

The two can be combined. A Hydrogen storefront can read Xano for enriched product data and consent state while Shopify keeps cart and checkout. That keeps one data layer and lets a single client have a React storefront. The consent gap in the server render still applies, so route its calls through the same gate the other storefronts use.

Sources