This episode spreads tRPC across various environments: integration with the Next.js App Router and pages router, usage in Remix and Astro, as well as serverless deployment on Vercel, Cloudflare Pages, and AWS Lambda.

After 15 episodes, you have a mature tRPC API. Now it's time to run it anywhere. Episode 16 covers tRPC integration with the Next.js App Router and pages router, usage in Remix and Astro, as well as serverless deployment on Vercel, Cloudflare Pages, and AWS Lambda.
The advantage of the tRPC architecture from episode 2 now pays off: the same router, different adapters.
You already saw the App Router pattern in episode 4: a single route handler file serves every procedure. For full-scale applications, add SSR hydration from episode 13:
import { fetchRequestHandler } from "@trpc/server/adapters/fetch";
import { createContext } from "@/server/api/context";
import { appRouter } from "@/server/api/root";
const handler = (req: Request) =>
fetchRequestHandler({
endpoint: "/api/trpc",
req,
router: appRouter,
createContext: () => createContext({ req }),
});
export { handler as GET, handler as POST };In a Server Component, create a caller per request and prefetch the query:
import { createCaller } from "@/server/api/root";
import { createContext } from "@/server/api/context";
import { QueryClient } from "@tanstack/react-query";
export default async function Page() {
const queryClient = new QueryClient();
const caller = createCaller(await createContext({}));
await queryClient.prefetchQuery({
queryKey: ["user.list"],
queryFn: () => caller.user.list(),
});
return <DaftarUser />;
}For the pages router, @trpc/next provides createTRPCNext, which handles SSR and the client at the same time:
import { createTRPCNext } from "@trpc/next";
import { httpBatchLink } from "@trpc/client";
import type { AppRouter } from "@/server/routers";
export const trpc = createTRPCNext<AppRouter>({
config() {
return {
links: [httpBatchLink({ url: "/api/trpc" })],
};
},
ssr: true,
});createTRPCNext wraps the app via trpc.withTRPC, and with ssr: true the data is prefetched on the server then hydrated on the client — an automatic dehydration pattern.
Remix uses loaders and actions for server data. tRPC is called inside them via a caller:
import { json, type LoaderFunctionArgs } from "@remix-run/node";
import { createCaller } from "~/server/root";
export async function loader({ request }: LoaderFunctionArgs) {
const caller = createCaller(await createContext({ request }));
const users = await caller.user.list();
return json({ users });
}The data from the loader is available in the component, and for client interactions the standard tRPC client can still be used with httpBatchLink. The principle: the server uses a caller, the browser uses a client proxy.
Astro can expose tRPC through a server endpoint with a Node or serverless adapter:
import { fetchRequestHandler } from "@trpc/server/adapters/fetch";
import type { APIRoute } from "astro";
import { appRouter } from "../server/root";
export const prerender = false;
export const ALL: APIRoute = ({ request }) =>
fetchRequestHandler({
endpoint: "/api/trpc",
req: request,
router: appRouter,
createContext: () => ({}),
});As long as the framework provides a point for HTTP functions, tRPC can be mounted — the fetchRequestHandler pattern is a universal bridge for fetch-based environments.
Because tRPC uses the fetch adapter, serverless deployment is almost unchanged. On Vercel, the Next.js route handler file works directly. On Cloudflare Pages Functions, mount a similar adapter:
import { fetchRequestHandler } from "@trpc/server/adapters/fetch";
import { appRouter } from "../server/root";
export async function onRequest(context) {
return fetchRequestHandler({
endpoint: "/api/trpc",
req: context.request,
router: appRouter,
createContext: () => ({}),
});
}onRequest receives the request and the Cloudflare context — a pattern identical to the fetch route handler. All tRPC procedures now run on the edge without a persistent server.
On AWS Lambda, wire the fetch handler to an API Gateway HTTP API or Lambda Function URL. For traditional deployment, run the tRPC server as a container on ECS or EKS — the standalone pattern from episode 4 with the graceful shutdown from episode 15.
Serverless environments have particular characteristics:
Tip
If your application has many subscriptions, consider separating WebSocket into a dedicated always-running service, while queries and mutations stay serverless. This architecture composition is common in production.
Episode 16 runs tRPC across various environments: Next.js with both routers, Remix and Astro via callers and fetch endpoints, and serverless deployment on Vercel, Cloudflare Pages, and AWS Lambda — with notes on stateless and WebSocket adjustments.
Key takeaways:
fetchRequestHandler; the pages router uses createTRPCNext.In the next episode, episode 17, we will discuss CI/CD, testing & production deployment — pipelines for building type-safe contracts and linting, unit and integration testing with vitest, msw, and procedure snapshots, as well as production deployment with environment configuration, observability, and release flow.