Skip to content

Run it in production

What RoutingCat adds to your pages, what visitors and records go through when RoutingCat can’t be reached, how routed pages work with caches, and how to upgrade, pause or remove RoutingCat. On Cloudflare, Cloudflare also gives the account’s and the zone’s settings.

Plan for its cost on each page

  • RoutingCat runs before each page, in your host’s middleware: Vercel’s root middleware.ts, or a Worker or Pages middleware on Cloudflare. It picks a visitor’s variants locally, from routing data it refreshes in the background, with no call to RoutingCat on the page’s path, and passes files such as images and stylesheets on untouched.
  • Your host bills its runs. On Vercel, the middleware runs as Routing Middleware, before Vercel’s cache, on every page request, prefetches included, and Vercel bills its runs to your account. On Cloudflare, Workers Paid includes 10 million requests and 30 million ms of CPU a month for $5, then bills $0.30 per million requests and $0.02 per million ms. RoutingCat’s Worker adds about 2 to 5 ms of CPU to a routed page, and since it runs first on every request, each file and each beacon through /_rc is a billed request too: at two requests a page view, 30 million views a month cost about $15.60 to $16.80 above the $5, against about $6.60 at one request a view.
  • Nothing RoutingCat sends delays a response. The middleware or Worker sends its records after the response, and the browser posts its reports without waiting for an answer.
  • Every variant is in the page. Each hidden variant adds its markup to the page’s HTML: a slot with three variants typically adds 1 to 3 KB, compressed. Their images are lazy, so a hidden variant’s image is never fetched.
  • The head partial adds its snippet, 1,244 bytes inline, which shows the selection, and the tracker’s script, which loads with defer, after the page is parsed.

Expect changes within about 2 minutes

  • Deploys and acts reach visitors within about 2 minutes on the instances that serve traffic. An instance idle for longer serves its next request with the routing data it had, then refreshes, so on a quiet site a paused variant can show once more.

  • A page’s first production deploy serves the page’s defaults for those 2 minutes on Vercel, recording arrivals but no decisions. On Cloudflare, the build waits up to a minute for routing data that knows the new page, and embeds it in the Worker, as the build log’s second line says:

    $ routingcat build
    routingcat LIVE home: 4 variants in hero, routing within about 2 minutes (ch_01m40j70srer495wr3vhnyvjca, pb_01m40j70srfb59gbvnmr3nv2t6)
    routingcat: this deployment embeds bd_9beb10d7c3b778de, compiled from this push.

    Past that minute, it ships with the routing data it started with, and says so:

    $ routingcat build
    routingcat LIVE home: 4 variants in hero, routing within about 2 minutes (ch_01m40j70srer495wr3vhnyvjca, pb_01m40j70srfb59gbvnmr3nv2t6)
    routingcat: the bundle compiled from this push did not come within 60 s, so this deployment keeps the exchange's snapshot.
  • Right after a deploy that adds a page, a slot or a variant, a new instance can hold its first routed requests for up to a second, while it fetches routing data that knows them.

Know what happens when RoutingCat is unreachable

Visitors always get a page.

What can’t reach RoutingCat Pages Records
A running deployment, for routing data Routing continues with the routing data each instance last had; a new instance starts from the copy its build embedded. Acts and new learning reach visitors once RoutingCat is back. Unaffected, unless ingestion is down too
A running deployment, for ingestion Unaffected The middleware’s or Worker’s records are retried once, then lost, and so are the browser’s reports. A backend calling the events API gets an error, and can retry safely, since each event carries its id.
A build The build ships as usual, with one line in its log, and its deployment shows your defaults. That deployment records nothing until a deploy that reaches RoutingCat.
The command It exits with code 4: run it again later.

A deployment whose build registered nothing records no visits and no conversions, from your pages or from the browser. After each deploy, look for RoutingCat’s line in the build log, or run npx routingcat doctor, and redeploy if the build didn’t register.

Keep caches from hiding decisions

  • A routed page is the same for every visitor, every variant in it, so it keeps your site’s own caching: Vercel’s cache serves it as usual, and so does your own server’s page cache, behind RoutingCat. Only its headers are each visitor’s: RoutingCat’s cookies, and Server-Timing, which carries the visitor’s selection to the head snippet.
  • Never cache routed pages’ HTML in front of RoutingCat. A CDN in front of Vercel, or a cache rule in front of your Worker, that serves your HTML from its own copy skips RoutingCat: visitors get a cached copy instead of their own variants, and their visits are not recorded. status then warns that render beacons outnumber decisions, and doctor names the cache in front. Caching files there is fine.
  • Keep Server-Timing on your pages. A header rule in vercel.json, or a proxy, that removes it leaves every visitor on the defaults, and doctor names it.
  • Cloudflare in front of Vercel works, since Cloudflare doesn’t cache HTML unless told to. Turn on its visitor-location headers: in Cloudflare, your domain → Rules → Settings → Managed Transforms → “Add visitor location headers”. Without them, visitors’ local times come from Cloudflare’s edge or from their country, and doctor and status say so. The zone’s Rocket Loader, Zaraz and cache rules act on your pages as on a site that runs on Cloudflare, and doctor checks them alike. Since the zone’s Early Hints would pass one visitor’s image preload to the next, RoutingCat’s middleware leaves the preload off for requests that come through the zone, until you turn it on. See Cloudflare.

Upgrade

  1. Upgrade the routingcat package with your package manager. It carries the command, the code your host runs and the agent skill, so they stay level.
  2. Run npx routingcat init. It brings the skill level with the package, unless the skill was edited here, which it keeps; doctor reports a skill older than the package. It also brings the note in AGENTS.md up to date, if you have it, and on Nuxt 2, RoutingCat’s entries in nuxt.config.js’s head.
  3. Run npx routingcat push, which writes the head partial this version makes, with its tracker, where your site has one; on plain HTML, paste the partial into each page again. Commit what changed: until you do, your build refuses a partial other than the one this version makes.
  4. Deploy, the Worker too where one stands in front of your server. Visitors get the new version only with your deploy, and builds install the version in your lockfile.

Learning, settings and acts never need an upgrade: they reach the version you deployed within about 2 minutes.

Pause or remove RoutingCat

  • Turn routing off for the whole site with npx routingcat set routing=off. Every page shows its defaults, and visits and conversions are still recorded. npx routingcat set routing=on resumes from what routing had learned. See Routing settings.

  • Remove it from your code in one change, then deploy:

    • in each slot, the container and every variant but the default, keeping the default’s content in place;

    • the head partial and the line that includes it; on plain HTML, its content in each page; on Nuxt 2, RoutingCat’s entries in nuxt.config.js’s head, and its router hook, plugins/routingcat.client.js, with its line in plugins;

    • your calls to the events API, and the browser script’s tag with its routingcat calls;

    • RoutingCat’s line in your PostHog init:

      public/index.html
      before_send: (event) => (window.routingcat ? routingcat.routingcatProperties(event) : event),
    • the host’s entry, middleware.ts, RoutingCat’s worker.ts with what init set in wrangler.jsonc, or functions/_middleware.ts; routingcat build in your build command, and before Wrangler’s server in your scripts; routingcat.config.json; .routingcat/ in .gitignore; on Laravel, the line that leaves rc_vid out of cookie encryption; the skill’s folders, .agents/skills/routingcat/ and .claude/skills/routingcat/; and the package;

    • the note for coding agents in AGENTS.md and CLAUDE.md, from <!-- routingcat --> to <!-- /routingcat -->, and AGENTS.md itself if the note is all it holds.

    A Worker in front of your server stays deployed on its route once its files leave your code: delete it in Cloudflare.

  • Archive the site. Archiving revokes the site’s keys and its binding to your host’s project, stops collection, and deletes the site’s records within 90 days, unless you ask otherwise. The site’s owner asks RoutingCat to archive it. To have the records deleted sooner, ask for their deletion.

Next