This episode brings your TanStack app to production: deployment strategies for Query and Router, hosting options for SPA and server-rendered apps, managing environment variables and runtime config, and build optimization for production.

Correct, validated, and built code isn't the end of the journey — an app only truly comes alive when it's deployed. Episode 20 covers production deployment for TanStack Query and Router apps: deployment strategies, hosting options for SPA and server-rendered apps, managing environment variables and runtime config, and build optimization for production.
Most TanStack apps take the form of an SPA or a hybrid with server rendering. Both forms have different hosting needs, and understanding the differences prevents problems that only appear once the app is online.
By the end of the episode, you'll know exactly where to deploy a TanStack app, how to manage configuration across environments, and what gets optimized during the production build.
TanStack Query works fully on the client side, so the Vite build output is static files that can be hosted on any CDN. The main challenge for an SPA is routing fallback: every URL request other than / must point back to index.html so TanStack Router can handle navigation.
npm run build
ls -la dist/The command npm run build produces a dist/ folder containing index.html and static assets. That's the folder you upload to static hosting like Vercel, Netlify, or Cloudflare Pages.
The process can be repeated on every change: rebuild, upload, and the CDN cache is invalidated automatically because asset names use hashes. Without a recorded process, deployment becomes error-prone manual work.
If you use Next.js or Remix, the build produces a server runtime instead of just static files. In Next.js, standalone mode lets you run the app in a container without a full installation. TanStack Query hydration still happens on the client after the HTML is sent.
node server.jsThe command node server.js runs the production server from the standalone output. The rendering load moves to the server, while the Query cache stays on the client to reduce repeated requests.
Vercel and Netlify detect Vite or Next.js projects automatically and set the build command and output directory themselves. Their framework presets handle SPA routing fallback without extra configuration.
For teams needing full control, the app is built into a container image and deployed to Kubernetes or a container platform. The production preview is identical to local: static files served by any HTTP server, with a fallback-to-index.html rule for all routes.
docker run -p 3000:3000 -e HOSTNAME=0.0.0.0 -e PORT=3000 \
registry.example.com/aplikasi-tanstack:latestThe flags -e HOSTNAME=0.0.0.0 -e PORT=3000 make sure the server listens on all interfaces inside the container. Environment variables are passed in when the container runs, not baked into the image.
Variables prefixed with NEXT_PUBLIC_ or VITE_ are baked into the bundle at build time. Their values can't change without a rebuild. For this reason, configuration that varies per environment should be read at runtime through a config endpoint.
VITE_API_URL=https://api.example.com npm run buildVITE_API_URL=https://api.example.com npm run build binds the API URL into the bundle. You'd have to run a separate build for each environment if you use the build-time approach.
For apps deployed to many environments from a single image, create a config file fetched at runtime, such as the /config.json endpoint. TanStack hooks read it before the first query runs, so API URL values can be swapped without rebuilding the image.
const { data: config } = useQuery({
queryKey: ["config"],
queryFn: () => fetch("/config.json").then((r) => r.json()),
staleTime: Infinity,
})
const baseUrl = config?.apiUrl ?? "/api"staleTime: Infinity prevents the config from being refetched repeatedly, since its value rarely changes. The fallback config?.apiUrl ?? "/api" keeps the app functional even if the config file is unavailable.
Vite and Rollup automatically perform tree shaking and code splitting for TanStack. Make sure libraries are imported from the package entry point, not internal paths, so the minifier can drop unused parts.
Assets given a content hash are automatically cached by the browser without problems, because the file name changes whenever the content changes. TanStack Router with the Vite plugin produces a chunk per route, so the first page only downloads the code it actually needs.
After the app goes live, verification doesn't stop at the page loading. Monitor server logs, Web Vitals, and the error rate during the first few days. Signals from this monitoring are what separate a smooth deployment from a lucky one.
Episode 20 wrapped up production deployment: SPA and server-rendered deploy strategies, hosting options from PaaS to containers, build-time environment variables and runtime config management, and bundle and asset optimization for production.
Key takeaways:
In the next episode, episode 21, we'll discuss observability and monitoring — monitoring data fetching and rendering on the client side, tracking cache behavior and query performance, error reporting for the UI and data layers, and performance and user experience analytics. Your app is online; now make sure it can be observed and fixed!