Skip to main content
Version: 9.x

Links & Request Batching

Similar to urql's exchanges or Apollo's links. Links enables you to customize the flow of data between tRPC Client and the tRPC-server.

Request Batchingโ€‹

Request batching is automatically enabled which batches your requests to the server, this can make the below code produce exactly one HTTP request and on the server exactly one database query:

ts
// below will be done in the same request when batching is enabled
const somePosts = await Promise.all([
client.query('post.byId', 1),
client.query('post.byId', 2),
client.query('post.byId', 3),
]);
ts
// below will be done in the same request when batching is enabled
const somePosts = await Promise.all([
client.query('post.byId', 1),
client.query('post.byId', 2),
client.query('post.byId', 3),
]);

Customizing data flowโ€‹

The below examples assuming you use Next.js, but the same as below can be added if you use the vanilla tRPC client

Setting a maximum batch sizeโ€‹

This limits the number of requests that can be sent together in batch ( useful to prevent the url from getting too large and run into HTTP error 413 ).

server.ts
ts
// ๐Ÿ‘‡ import the httpBatchLink
import { httpBatchLink } from '@trpc/client/links/httpBatchLink';
import { withTRPC } from '@trpc/next';
import { AppType } from 'next/dist/shared/lib/utils';
import type { AppRouter } from 'pages/api/trpc/[trpc]';
const MyApp: AppType = ({ Component, pageProps }) => {
return <Component {...pageProps} />;
};
export default withTRPC<AppRouter>({
config() {
return {
links: [
httpBatchLink({
url: '/api/trpc',
maxBatchSize: 10, // a reasonable size
}),
],
};
},
})(MyApp);
server.ts
ts
// ๐Ÿ‘‡ import the httpBatchLink
import { httpBatchLink } from '@trpc/client/links/httpBatchLink';
import { withTRPC } from '@trpc/next';
import { AppType } from 'next/dist/shared/lib/utils';
import type { AppRouter } from 'pages/api/trpc/[trpc]';
const MyApp: AppType = ({ Component, pageProps }) => {
return <Component {...pageProps} />;
};
export default withTRPC<AppRouter>({
config() {
return {
links: [
httpBatchLink({
url: '/api/trpc',
maxBatchSize: 10, // a reasonable size
}),
],
};
},
})(MyApp);

Disabling request batchingโ€‹

1. Disable batching on your server:โ€‹

In your [trpc].ts:

pages/api/trpc/[trpc].ts
ts
export default trpcNext.createNextApiHandler({
// [...]
// ๐Ÿ‘‡ disable batching
batching: {
enabled: false,
},
});
pages/api/trpc/[trpc].ts
ts
export default trpcNext.createNextApiHandler({
// [...]
// ๐Ÿ‘‡ disable batching
batching: {
enabled: false,
},
});
pages/_app.tsx
tsx
// ๐Ÿ‘‡ import the httpLink
import { httpLink } from '@trpc/client/links/httpLink';
import { withTRPC } from '@trpc/next';
import { AppType } from 'next/dist/shared/lib/utils';
import type { AppRouter } from 'pages/api/trpc/[trpc]';
const MyApp: AppType = ({ Component, pageProps }) => {
return <Component {...pageProps} />;
};
export default withTRPC<AppRouter>({
config() {
return {
links: [
httpLink({
url: '/api/trpc',
}),
],
};
},
// ssr: false,
})(MyApp);
pages/_app.tsx
tsx
// ๐Ÿ‘‡ import the httpLink
import { httpLink } from '@trpc/client/links/httpLink';
import { withTRPC } from '@trpc/next';
import { AppType } from 'next/dist/shared/lib/utils';
import type { AppRouter } from 'pages/api/trpc/[trpc]';
const MyApp: AppType = ({ Component, pageProps }) => {
return <Component {...pageProps} />;
};
export default withTRPC<AppRouter>({
config() {
return {
links: [
httpLink({
url: '/api/trpc',
}),
],
};
},
// ssr: false,
})(MyApp);

Disable batching for certain requestsโ€‹

1. Configure client / _app.tsxโ€‹
pages/_app.tsx
tsx
import { httpBatchLink } from '@trpc/client/links/httpBatchLink';
import { httpLink } from '@trpc/client/links/httpLink';
import { splitLink } from '@trpc/client/links/splitLink';
import { withTRPC } from '@trpc/next';
// [..]
export default withTRPC<AppRouter>({
config() {
const url = `http://localhost:3000`;
return {
links: [
splitLink({
condition(op) {
// check for context property `skipBatch`
return op.context.skipBatch === true;
},
// when condition is true, use normal request
true: httpLink({
url,
}),
// when condition is false, use batching
false: httpBatchLink({
url,
}),
}),
],
};
},
})(MyApp);
pages/_app.tsx
tsx
import { httpBatchLink } from '@trpc/client/links/httpBatchLink';
import { httpLink } from '@trpc/client/links/httpLink';
import { splitLink } from '@trpc/client/links/splitLink';
import { withTRPC } from '@trpc/next';
// [..]
export default withTRPC<AppRouter>({
config() {
const url = `http://localhost:3000`;
return {
links: [
splitLink({
condition(op) {
// check for context property `skipBatch`
return op.context.skipBatch === true;
},
// when condition is true, use normal request
true: httpLink({
url,
}),
// when condition is false, use batching
false: httpBatchLink({
url,
}),
}),
],
};
},
})(MyApp);
2. Perform request without batchingโ€‹
MyComponent.tsx
tsx
export function MyComponent() {
const postsQuery = trpc.useQuery(['posts'], {
context: {
skipBatch: true,
},
});
return (
<pre>{JSON.stringify(postsQuery.data ?? null, null, 4)}</pre>
)
})
MyComponent.tsx
tsx
export function MyComponent() {
const postsQuery = trpc.useQuery(['posts'], {
context: {
skipBatch: true,
},
});
return (
<pre>{JSON.stringify(postsQuery.data ?? null, null, 4)}</pre>
)
})

or:

client.ts
ts
const postResult = client.query('posts', null, {
context: {
skipBatch: true,
},
});
client.ts
ts
const postResult = client.query('posts', null, {
context: {
skipBatch: true,
},
});
pages/_app.tsx
tsx
import { TRPCLink } from '@trpc/client';
import type { AppRouter } from 'pages/api/trpc/[trpc]';
const customLink: TRPCLink<AppRouter> = (runtime) => {
// here we just got initialized in the app - this happens once per app
// useful for storing cache for instance
return ({ prev, next, op }) => {
// this is when passing the result to the next link
next(op, (result) => {
// this is when we've gotten result from the server
if (result instanceof Error) {
// maybe send to bugsnag?
}
prev(result);
});
};
};
export default withTRPC<AppRouter>({
config() {
return {
links: [
customLink,
// [..]
// โ— Make sure to end with a `httpBatchLink` or `httpLink`
],
};
},
// ssr: false
})(MyApp);
pages/_app.tsx
tsx
import { TRPCLink } from '@trpc/client';
import type { AppRouter } from 'pages/api/trpc/[trpc]';
const customLink: TRPCLink<AppRouter> = (runtime) => {
// here we just got initialized in the app - this happens once per app
// useful for storing cache for instance
return ({ prev, next, op }) => {
// this is when passing the result to the next link
next(op, (result) => {
// this is when we've gotten result from the server
if (result instanceof Error) {
// maybe send to bugsnag?
}
prev(result);
});
};
};
export default withTRPC<AppRouter>({
config() {
return {
links: [
customLink,
// [..]
// โ— Make sure to end with a `httpBatchLink` or `httpLink`
],
};
},
// ssr: false
})(MyApp);