FX auto-refresh
Refresh exchange rates daily from the ECB feed into a DB override, read as dbRate ?? staticAnchor — display and checkout always resolve the same rate.
fxAutoUpdate keeps multi-currency exchange rates current by refreshing them daily from the European Central Bank's no-key feed into a database override, instead of relying on the static rates in brand.config.ts. It builds on Multi-currency.
Why a DB override
The static rates in brand.config.ts are compile-time constants — a cron can't rewrite a .ts file. So fxAutoUpdate writes refreshed rates to IntegrationSettings.fxRatesJson and the rate resolver reads:
dbRate ?? staticAnchorWhen the flag is off (or no rates have been fetched), resolution falls back to the static brand.config anchors — behaviour is byte-identical to before.
Same rate for display and charge
The override is read through the one conversion path in lib/money.ts (fxRate/convertMinor), shared by storefront display, checkout, the order snapshot, and the receipt email — so there's no drift between the price shown and the amount charged. (The order also snapshots Order.fxRate, so receipts match the charge even if rates move later.)
Enable it
supportedCurrencies and multi-currency working.fxAutoUpdate in /admin/features (runtime).CRON_SECRET — /api/cron/fx-refresh runs daily and no-ops when the flag is off.| Flag | fxAutoUpdate |
| Tier | runtime (needs ≥2 currencies) |
| Default | off |
| Env | none for rates (ECB is keyless); CRON_SECRET for the cron |
Fail-soft: if the ECB feed is unreachable the last good rates are kept; the static anchors are never dropped.
Multi-currency
Charge customers in their own currency — Stripe presentment currency, an order-time snapshot, and a single conversion path shared by display and checkout.
Internationalization (i18n)
Ship multiple languages from day one — locales declared in brand.config, automatic hreflang, and per-entity content translation with AI auto-translate.