Dispatchers are the central abstraction in undici. Every HTTP request flows through a dispatcher, which is responsible for managing connections, sending requests, and delivering responses. Whether you use the high-levelDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/nodejs/undici/llms.txt
Use this file to discover all available pages before exploring further.
request() function or configure a custom Agent, you are always working with a dispatcher under the hood.
What is a dispatcher?
Dispatcher is an abstract base class that extends Node.js EventEmitter. It defines the contract that all HTTP dispatch implementations must follow. You never instantiate Dispatcher directly — instead you use one of its concrete subclasses.
The class is defined in lib/dispatcher/dispatcher.js and exposes three abstract methods that subclasses must implement:
dispatcher.js (simplified)
request, stream, pipeline, connect, upgrade) are mixed in from lib/api via Object.assign(Dispatcher.prototype, api) in index.js.
The dispatcher hierarchy
undici ships several built-in dispatcher implementations. Each one is appropriate for different use cases.Client
A single HTTP/1.1 connection to one origin. Pipelining is disabled by default (
pipelining: 1). Use when you need precise control over one connection.Pool
Multiple
Client instances connected to the same origin. Distributes requests across connections. The connections option controls the pool size.BalancedPool
Weighted round-robin load balancing across multiple upstream origins. Useful for distributing load across a set of backend servers.
Agent
Automatically manages a pool per origin. This is the default global dispatcher. The factory function creates a
Pool (or Client when connections: 1).ProxyAgent
Routes requests through an HTTP or HTTPS proxy. Extends
Agent with proxy-aware connection logic.RetryAgent
Wraps another dispatcher and adds automatic retry logic at the agent level.
Key methods
Every dispatcher exposes the same set of methods inherited fromDispatcher.
dispatch(options, handler)
The lowest-level API. All other methods are implemented on top of dispatch. It accepts a DispatchOptions object and a DispatchHandler object, and returns false if the dispatcher is busy (back-pressure signal).
dispatch a GET request
request(options[, callback])
Performs an HTTP request and resolves with { statusCode, headers, body, trailers }. The body is a stream.Readable that also implements the Fetch body mixin (json(), text(), arrayBuffer(), etc.).
request with body consumption
stream(options, factory[, callback])
A faster variant of request that writes the response body directly into a stream.Writable returned by the factory function. This avoids creating an intermediate Readable stream.
pipeline(options, handler)
Designed for use with stream.pipeline. The handler receives { statusCode, headers, body } and must return a stream.Readable. Returns a stream.Duplex.
connect(options[, callback])
Initiates an HTTP CONNECT tunnel. Returns a raw stream.Duplex socket for two-way communication.
upgrade(options[, callback])
Upgrades an HTTP connection to a different protocol (e.g., WebSocket). Returns the upgraded socket.
The handler object
When callingdispatch() directly you must provide a handler. The handler is a plain object with lifecycle callbacks:
onRequestStart(controller, context)
onRequestStart(controller, context)
Called before the request is dispatched on the socket. May be called multiple times if the request is retried. Use
controller.abort(reason) to cancel.onResponseStart(controller, statusCode, headers, statusMessage)
onResponseStart(controller, statusCode, headers, statusMessage)
Called when the status code and headers have been received. May be called multiple times for 1xx informational responses.
onResponseData(controller, chunk)
onResponseData(controller, chunk)
Called for each chunk of response body data received.
onResponseEnd(controller, trailers)
onResponseEnd(controller, trailers)
Called when the response body and any trailers have been fully received.
onResponseError(controller, error)
onResponseError(controller, error)
Called when an error occurs. Must not throw.
onRequestUpgrade(controller, statusCode, headers, socket)
onRequestUpgrade(controller, statusCode, headers, socket)
Required when
options.upgrade is set or method is CONNECT. Called when the protocol upgrade is complete.controller object passed to each callback provides pause(), resume(), and abort(reason) methods to control backpressure and cancellation. Raw headers are accessible via controller.rawHeaders.
The global dispatcher
undici maintains a global dispatcher used by the top-levelrequest, fetch, and other convenience functions. By default it is a new Agent instance, initialized in lib/global.js:
lib/global.js (simplified)
Dispatcher implementation:
setting a custom global dispatcher
setGlobalDispatcher also mirrors the agent to Symbol.for('undici.globalDispatcher.1') using a Dispatcher1Wrapper so Node.js built-in fetch can continue using the legacy handler interface.Composing dispatchers with .compose()
Every dispatcher exposes a .compose() method that wraps it with one or more interceptor functions, returning a new dispatcher. Interceptors follow the pattern dispatch => (opts, handler) => dispatch(opts, handler).
compose() implementation (simplified)
[interceptor1, interceptor2, interceptor3], the request flows through them in reverse order: interceptor3 runs first, interceptor1 last.
chaining interceptors with compose
compose with array of interceptors
HTTP pipelining
HTTP/1.1 pipelining allows sending multiple requests on a single connection without waiting for each response. undici implements pipelining via thepipelining option on Client or Pool.
- Default (no pipelining)
- Pipelining enabled
default pipelining of 1
blocking option on individual requests controls pipelining behavior per-request. When blocking: true, no further pipelining occurs on that connection until the response headers are received. For requests expected to take a long time, set blocking: true to avoid holding up other requests.
blocking option per request
Lifecycle events
All dispatchers emit the following events:| Event | Parameters | Description |
|---|---|---|
connect | origin, targets | Emitted when a socket connects to the origin. |
disconnect | origin, targets, error | Emitted when a socket disconnects. |
connectionError | origin, targets, error | Emitted when a connection attempt fails. |
drain | origin | Emitted when the dispatcher is no longer busy. |