Skip to main content
Version: 11.x

HTTP Batch Link

httpBatchLink is a terminating link that batches an array of individual tRPC operations into a single HTTP request that's sent to a single tRPC procedure.

Usage

You can import and add the httpBatchLink to the links array as such:

client/index.ts
ts
import { createTRPCClient, httpBatchLink } from '@trpc/client';
import type { AppRouter } from '../server';
const client = createTRPCClient<AppRouter>({
links: [
httpBatchLink({
url: 'http://localhost:3000',
}),
// transformer,
],
});
client/index.ts
ts
import { createTRPCClient, httpBatchLink } from '@trpc/client';
import type { AppRouter } from '../server';
const client = createTRPCClient<AppRouter>({
links: [
httpBatchLink({
url: 'http://localhost:3000',
}),
// transformer,
],
});

After that, you can make use of batching by setting all your procedures in a Promise.all. The code below will produce exactly one HTTP request and on the server exactly one database query:

ts
const somePosts = await Promise.all([
trpc.post.byId.query(1),
trpc.post.byId.query(2),
trpc.post.byId.query(3),
]);
ts
const somePosts = await Promise.all([
trpc.post.byId.query(1),
trpc.post.byId.query(2),
trpc.post.byId.query(3),
]);

The httpBatchLink function takes an options object that has the HTTPBatchLinkOptions shape.

ts
export interface HTTPBatchLinkOptions extends HTTPLinkOptions {
maxURLLength?: number;
}
export interface HTTPLinkOptions {
url: string;
/**
* Add ponyfill for fetch
*/
fetch?: typeof fetch;
/**
* Add ponyfill for AbortController
*/
AbortController?: typeof AbortController | null;
/**
* Data transformer
* @link https://trpc.io/docs/data-transformers
**/
transformer?: DataTransformerOptions;
/**
* Headers to be set on outgoing requests or a callback that of said headers
* @link http://trpc.io/docs/header
*/
headers?:
| HTTPHeaders
| ((opts: { opList: Operation[] }) => HTTPHeaders | Promise<HTTPHeaders>);
}
ts
export interface HTTPBatchLinkOptions extends HTTPLinkOptions {
maxURLLength?: number;
}
export interface HTTPLinkOptions {
url: string;
/**
* Add ponyfill for fetch
*/
fetch?: typeof fetch;
/**
* Add ponyfill for AbortController
*/
AbortController?: typeof AbortController | null;
/**
* Data transformer
* @link https://trpc.io/docs/data-transformers
**/
transformer?: DataTransformerOptions;
/**
* Headers to be set on outgoing requests or a callback that of said headers
* @link http://trpc.io/docs/header
*/
headers?:
| HTTPHeaders
| ((opts: { opList: Operation[] }) => HTTPHeaders | Promise<HTTPHeaders>);
}

Setting a maximum URL length

When sending batch requests, sometimes the URL can become too large causing HTTP errors like 413 Payload Too Large, 414 URI Too Long, and 404 Not Found. The maxURLLength option will limit the number of requests that can be sent together in a batch.

An alternative way of doing this is to

client/index.ts
ts
import { createTRPCClient, httpBatchLink } from '@trpc/client';
import type { AppRouter } from '../server';
const client = createTRPCClient<AppRouter>({
links: [
httpBatchLink({
url: 'http://localhost:3000',
maxURLLength: 2083, // a suitable size
// alternatively, you can make all RPC-calls to be called with POST
// methodOverride: 'POST',
}),
],
});
client/index.ts
ts
import { createTRPCClient, httpBatchLink } from '@trpc/client';
import type { AppRouter } from '../server';
const client = createTRPCClient<AppRouter>({
links: [
httpBatchLink({
url: 'http://localhost:3000',
maxURLLength: 2083, // a suitable size
// alternatively, you can make all RPC-calls to be called with POST
// methodOverride: 'POST',
}),
],
});

Disabling request batching

1. Disable batching on your server:

server.ts
ts
import { createHTTPServer } from '@trpc/server/adapters/standalone';
createHTTPServer({
// [...]
// 👇 disable batching
allowBatching: false,
});
server.ts
ts
import { createHTTPServer } from '@trpc/server/adapters/standalone';
createHTTPServer({
// [...]
// 👇 disable batching
allowBatching: false,
});

or, if you're using Next.js:

pages/api/trpc/[trpc].ts
ts
export default trpcNext.createNextApiHandler({
// [...]
// 👇 disable batching
allowBatching: false,
});
pages/api/trpc/[trpc].ts
ts
export default trpcNext.createNextApiHandler({
// [...]
// 👇 disable batching
allowBatching: false,
});
client/index.ts
ts
import { createTRPCClient, httpLink } from '@trpc/client';
import type { AppRouter } from '../server';
const client = createTRPCClient<AppRouter>({
links: [
httpLink({
url: 'http://localhost:3000',
}),
],
});
client/index.ts
ts
import { createTRPCClient, httpLink } from '@trpc/client';
import type { AppRouter } from '../server';
const client = createTRPCClient<AppRouter>({
links: [
httpLink({
url: 'http://localhost:3000',
}),
],
});

or, if you're using Next.js:

utils/trpc.ts
tsx
import type { AppRouter } from '@/server/routers/app';
import { httpLink } from '@trpc/client';
import { createTRPCNext } from '@trpc/next';
export const trpc = createTRPCNext<AppRouter>({
config() {
return {
links: [
httpLink({
url: '/api/trpc',
}),
],
};
},
});
utils/trpc.ts
tsx
import type { AppRouter } from '@/server/routers/app';
import { httpLink } from '@trpc/client';
import { createTRPCNext } from '@trpc/next';
export const trpc = createTRPCNext<AppRouter>({
config() {
return {
links: [
httpLink({
url: '/api/trpc',
}),
],
};
},
});