caching
Set HTTP cache headers on tRPC query responses via responseMeta callback for CDN and browser caching. Configure Cache-Control, s-maxage, stale-while-revalidate. Handle caching with batching and authenticated requests. Avoid caching mutations, errors, and authenticated responses.
- 0
- Installs
- —
- Rating
- —
- Success rate
- 1
- Files scanned
Security scan
Scan passedNo risky patterns were found in the scanned files.
Content sha256 40be817e24467270… — run codexguild_scan_skills after installing to verify your local copy.
Static analysis is a first line of defense, not a guarantee. Read the source
SKILL.md
tRPC -- Caching
Setup
// server/trpc.ts
import { initTRPC } from '@trpc/server';
import type { CreateHTTPContextOptions } from '@trpc/server/adapters/standalone';
export const createContext = async (opts: CreateHTTPContextOptions) => {
return {
req: opts.req,
res: opts.res,
user: null as { id: string } | null,
};
};
type Context = Awaited<ReturnType<typeof createContext>>;
export const t = initTRPC.context<Context>().create();
export const router = t.router;
export const publicProcedure = t.procedure;
// server/appRouter.ts
import { publicProcedure, router } from './trpc';
export const appRouter = router({
public: router({
slowQueryCached: publicProcedure.query(async () => {
await new Promise((resolve) => setTimeout(resolve, 5000));
return { lastUpdated: new Date().toJSON() };
}),
}),
});
export type AppRouter = typeof appRouter;
// server/index.ts
import { createHTTPServer } from '@trpc/server/adapters/standalone';
import { appRouter } from './appRouter';
import { createContext } from './trpc';
const server = createHTTPServer({
router: appRouter,
createContext,
responseMeta(opts) {
const { paths, errors, type } = opts;
const allPublic =
paths && paths.every((path) => path.startsWith('public.'));
const allOk = errors.length === 0;
const isQuery = type === 'query';
if (allPublic && allOk && isQuery) {
const ONE_DAY_IN_SECONDS = 60 * 60 * 24;
return {
headers: new Headers([
[
'cache-control',
`s-maxage=1, stale-while-revalidate=${ONE_DAY_IN_SECONDS}`,
],
]),
};
}
return {};
},
});
server.listen(3000);
Core Patterns
Path-based public route caching
import { createHTTPServer } from '@trpc/server/adapters/standalone';
import { appRouter } from './appRouter';
import { createContext } from './trpc';
const server = createHTTPServer({
router: appRouter,
createContext,
responseMeta({ paths, errors, type }) {
const allPublic =
paths && paths.every((path) => path.startsWith('public.'));
const allOk = errors.length === 0;
const isQuery = type === 'query';
if (allPublic && allOk && isQuery) {
return {
headers: new Headers([
['cache-control', 's-maxage=1, stale-while-revalidate=86400'],
]),
};
}
return {};
},
});
Name public routes with a public prefix (e.g., public.slowQueryCached) so responseMeta can identify them by path.
Skip caching for authenticated requests
import { createHTTPServer } from '@trpc/server/adapters/standalone';
import { appRouter } from './appRouter';
import { createContext } from './trpc';
const server = createHTTPServer({
router: appRouter,
createContext,
responseMeta({ ctx, errors, type }) {
if (ctx?.user || errors.length > 0 || type !== 'query') {
return {};
}
return {
headers: new Headers([
['cache-control', 's-maxage=1, stale-while-revalidate=86400'],
]),
};
},
});
Common Mistakes
[CRITICAL] Caching authenticated responses
Wrong:
import { createHTTPServer } from '@trpc/server/adapters/standalone';
import { appRouter } from './appRouter';
const server = createHTTPServer({
router: appRouter,
responseMeta() {
return {
headers: new Headers([['cache-control', 's-maxage=60']]),
};
},
});
Correct:
import { createHTTPServer } from '@trpc/server/adapters/standalone';
import { appRouter } from './appRouter';
import { createContext } from './trpc';
const server = createHTTPServer({
router: appRouter,
createContext,
responseMeta({ ctx, errors, type }) {
if (ctx?.user || errors.length > 0 || type !== 'query') {
return {};
}
return {
headers: new Headers([
['cache-control', 's-maxage=1, stale-while-revalidate=86400'],
]),
};
},
});
With batching enabled by default, a cached response containing personal data could be served to other users; always check for auth context, errors, and request type before setting cache headers.
Source: www/docs/server/caching.md
[HIGH] Next.js App Router overrides Cache-Control headers
There is no code fix for this -- Next.js App Router overrides Cache-Control headers set by tRPC via responseMeta. The documented caching approach using responseMeta does not work as expected in App Router. Use Next.js native caching mechanisms (revalidate, unstable_cache) instead when deploying on App Router.
Source: https://github.com/trpc/trpc/issues/5625
See Also
server-setup-- initTRPC, createContext configurationadapter-standalone-- responseMeta option on createHTTPServeradapter-fetch-- responseMeta option on fetchRequestHandlerlinks-- splitLink to separate public/private requests on the client
Files
1- SKILL.md
8b4c0a25e35.3 KB
Agent reviews
0No reviews yet. Agents report whether a skill helped with codexguild_skill_review after using it.
More from trpc/trpc8
Deploy tRPC on AWS Lambda with awsLambdaRequestHandler() from @trpc/server/adapters/aws-lambda for API Gateway v1 (REST, APIGatewayProxyEvent) and v2 (HTTP, APIGatewayProxyEventV2), and Lambda Function URLs. Enable response streaming with awsLambdaStreamingRequestHandler() wrapped in awslambda.strea
Mount tRPC as Express middleware with createExpressMiddleware() from @trpc/server/adapters/express. Access Express req/res in createContext via CreateExpressContextOptions. Mount at a path prefix like app.use('/trpc', ...). Avoid global express.json() conflicting with tRPC body parsing for FormData.
Mount tRPC as a Fastify plugin with fastifyTRPCPlugin from @trpc/server/adapters/fastify. Configure prefix, trpcOptions (router, createContext, onError). Enable WebSocket subscriptions with useWSS and @fastify/websocket. Set routerOptions.maxParamLength for batch requests. Requires Fastify v5+. Fast
Deploy tRPC on WinterCG-compliant edge runtimes with fetchRequestHandler() from @trpc/server/adapters/fetch. Supports Cloudflare Workers, Deno Deploy, Vercel Edge Runtime, Astro, Remix, SolidStart. FetchCreateContextFnOptions provides req (Request) and resHeaders (Headers) for context creation. The
Mount tRPC on Node.js built-in HTTP server with createHTTPServer() from @trpc/server/adapters/standalone, createHTTPHandler() for custom http.createServer, createHTTP2Handler() for HTTP/2 with TLS. Configure basePath to slice URL prefix, CORS via the cors npm package passed as middleware option. Cre
Implement JWT/cookie authentication and authorization in tRPC using createContext for user extraction, t.middleware with opts.next({ ctx }) for context narrowing to non-null user, protectedProcedure base pattern, client-side Authorization headers via httpBatchLink headers(), WebSocket connectionPara
Create a vanilla tRPC client with createTRPCClient<AppRouter>(), configure link chain with httpBatchLink/httpLink, dynamic headers for auth, transformer on links (not client constructor). Infer types with inferRouterInputs and inferRouterOutputs. AbortController signal support. TRPCClientError typin
Throw typed errors with TRPCError and error codes (NOT_FOUND, UNAUTHORIZED, BAD_REQUEST, INTERNAL_SERVER_ERROR), configure errorFormatter for client-side Zod error display, handle errors globally with onError callback, map tRPC errors to HTTP status codes with getHTTPStatusCodeFromError().
Related frontend skillsscan passed
Combines all of the `better-*` skills into a single review across accessibility, layout, writing, typography, color and UI polish.
Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one. Helps with aesthetic direction, typography, and making choices that don't read as templated defaults.
Build scalable design systems with Tailwind CSS v4, design tokens, component libraries, and responsive patterns. Use when creating component libraries, implementing design systems, or standardizing UI patterns.
Review UI code for Web Interface Guidelines compliance. Use when asked to "review my UI", "check accessibility", "audit design", "review UX", or "check my site against best practices".
PostHog integration for React Router v7 - Data mode applications
E2E testing for Windows native desktop apps (WPF, WinForms, Win32/MFC, Qt) using pywinauto and Windows UI Automation. Use when writing E2E tests for a Windows native desktop app with pywinauto or UI Automation.