new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Bun · Runtime · all subjects

networking

71 notes in this subject, read out of this brain and free to use. This is page 1 of 2.

UDP socket API

UDP sockets in Bun are created using Bun.udpSocket().

fetch request options supported by Bun

Bun's fetch implementation is fully implemented. The integrity option is ignored. Request options missing keepalive and duplex; credentials, integrity, referrer and referrerPolicy options are accepted but ignored.

node:quic implementation

node:quic is implemented: listen(), connect(), QuicEndpoint, QuicSession and QuicStream. 99% of Node.js's test suite passes. The API is experimental in Node.js, and importing it emits an ExperimentalWarning in Bun too.

Request global missing features

Request global is missing keepalive and duplex options. The credentials, integrity, referrer and referrerPolicy options are accepted but ignored.

BUN_CONFIG_MAX_HTTP_REQUESTS environment variable

To raise the simultaneous fetch request limit beyond the default 256, set the BUN_CONFIG_MAX_HTTP_REQUESTS environment variable. The max value is 65,535.

dns.prefetch for DNS optimization

Use dns.prefetch(hostname) from the bun module when you know you'll connect to a host soon to avoid the initial DNS lookup delay.

DNS caching default behavior

By default, Bun caches and deduplicates DNS queries in-memory for up to 30 seconds. Use dns.getCacheStats() to return the cache statistics.

fetch.preconnect for connection setup optimization

Use fetch.preconnect(url) to start the DNS lookup, TCP socket connection, and TLS handshake for a host before sending a request to it. Calling fetch immediately after preconnect does not make the request faster; preconnecting only helps when there's a gap between knowing the host and sending the request.

fetch --fetch-preconnect CLI flag

Pass --fetch-preconnect https://hostname when running bun to preconnect to a host at startup. This is similar to <link rel="preconnect"> in HTML and is not implemented on Windows.

fetch connection pooling and HTTP keep-alive

Bun automatically reuses connections to the same host for connection pooling. You can disable it per-request with keepalive: false or the 'Connection: close' header.

fetch simultaneous request limit default

By default, Bun limits the number of simultaneous fetch requests to 256 to improve system stability and encourage HTTP Keep-Alive connection reuse. When the limit is exceeded, Bun queues requests and sends them as soon as the next request ends.

UDP source-specific multicast (SSM) methods

Use socket.addSourceSpecificMembership(sourceAddress, multicastAddress) to join a source-specific multicast group, where both arguments are IP address strings. Use socket.dropSourceSpecificMembership(sourceAddress, multicastAddress) to leave a source-specific multicast group.

Bun.udpSocket() basic example

const socket = await Bun.udpSocket({}); console.log(socket.port); // assigned by the operating system

Bun.udpSocket() with specific port example

const socket = await Bun.udpSocket({ port: 41234, }); console.log(socket.port); // 41234

UDP socket connect example

const server = await Bun.udpSocket({ socket: { data(socket, buf, port, addr) { console.log(`message from ${addr}:${port}:`); console.log(buf.toString()); }, }, }); const client = await Bun.udpSocket({ connect: { port: server.port, hostname: "127.0.0.1", }, }); client.send("Hello");

UDP sendMany() for unconnected socket example

const socket = await Bun.udpSocket({}); // sends 'Hello' to 127.0.0.1:41234, and 'foo' to 1.1.1.1:53 in a single operation socket.sendMany(["Hello", 41234, "127.0.0.1", "foo", 53, "1.1.1.1"]);

UDP sendMany() for connected socket example

const socket = await Bun.udpSocket({ connect: { port: 41234, hostname: "localhost", }, }); socket.sendMany(["foo", "bar", "baz"]);

UDP socket data callback receives incoming packets

Pass a data callback in the socket option when creating a UDP socket to handle incoming packets. The callback signature is data(socket, buf, port, addr) where socket is the UDP socket object, buf is a Buffer containing the packet data, port is the source port number, and addr is the source IP address as a string.

UDP socket send() method sends a single datagram

Use socket.send(data, port, address) to send a datagram. The data can be a string or buffer. Port is a number representing the destination port. Address must be a valid IP address as a string. The send() method does not perform DNS resolution. It returns false if the packet does not fit into the operating system's packet buffer.

Bun.udpSocket() creates a bound UDP socket

Call Bun.udpSocket() to create a new bound UDP socket. It returns a promise that resolves to the socket object. The socket object has a port property that contains the assigned port number. You can optionally specify a port in the options object, otherwise the operating system assigns one.

UDP socket sendMany() batches multiple packets

Use socket.sendMany() to send multiple packets without a system call for each packet. For an unconnected socket, pass an array where each set of three elements is: data (string or buffer), port (number), and address (string). For a connected socket, pass an array where each element is data. The method returns the number of packets successfully sent.

UDP backpressure detection and drain callback

When send() returns false or sendMany() returns fewer packets than specified, backpressure has occurred because the packet did not fit in the operating system's buffer. Define a drain(socket) callback in the socket option to be notified when the socket becomes writable again, allowing you to resume sending data.

UDP socket connect() establishes a connection to a peer

Pass a connect object when creating a UDP socket to connect to a specific peer. The connect object has properties: port (number) and hostname (string). Once connected, send() requires only the data argument, and incoming packets are restricted to the connected peer. Connections are implemented at the operating system level and can improve performance.

UDP socket option methods: setBroadcast, setTTL

Call socket.setBroadcast(true) to enable broadcasting for sending packets to a broadcast address. Call socket.setTTL(number) to set the IP TTL (time to live) for outgoing packets, where number is the TTL value (e.g., 64).

UDP multicast membership methods

Use socket.addMembership(address) to join a multicast group, where address is a multicast address string like '224.0.0.1'. You can optionally pass a second argument for a specific interface IP. Use socket.dropMembership(address) to leave a multicast group.

UDP multicast option methods

Call socket.setMulticastTTL(number) to set the TTL for multicast packets (number of network hops). Call socket.setMulticastLoopback(boolean) to control whether multicast packets loop back to the local socket. Call socket.setMulticastInterface(address) where address is an IP address string to specify which interface to use for outgoing multicast packets.

Redis duplicate connection for pub/sub example

Example showing how to use duplicate() to create separate connection for commands while one is subscribed: import { RedisClient } from 'bun'; const redis = new RedisClient('redis://localhost:6379'); await redis.connect(); const subscriber = await redis.duplicate(); await subscriber.subscribe('foo', () => {}); await redis.set('bar', 'baz');

Redis automatic pipelining example

Example showing automatic command pipelining: const [infoResult, listResult] = await Promise.all([ redis.get('user:1:name'), redis.get('user:2:email') ]);

Redis disable auto pipelining example

Example of disabling automatic pipelining: const client = new RedisClient('redis://localhost:6379', { enableAutoPipelining: false });

Redis send raw command example

Example showing raw command execution with send(): const info = await redis.send('INFO', []); await redis.send('LPUSH', ['mylist', 'value1', 'value2']); const list = await redis.send('LRANGE', ['mylist', '0', '-1']);

Redis connection events example

Example of registering connection event handlers: const client = new RedisClient(); client.onconnect = () => { console.log('Connected to Redis server'); }; client.onclose = error => { console.error('Disconnected from Redis server:', error); }; await client.connect(); client.close();

Redis caching use case example

Example of using Redis for caching: async function getUserWithCache(userId) { const cacheKey = `user:${userId}`; const cachedUser = await redis.get(cacheKey); if (cachedUser) { return JSON.parse(cachedUser); } const user = await database.getUser(userId); await redis.set(cacheKey, JSON.stringify(user)); await redis.expire(cacheKey, 3600); return user; }

Redis rate limiting use case example

Example of using Redis for rate limiting: async function rateLimit(ip, limit = 100, windowSecs = 3600) { const key = `ratelimit:${ip}`; const count = await redis.incr(key); if (count === 1) { await redis.expire(key, windowSecs); } return { limited: count > limit, remaining: Math.max(0, limit - count), }; }

Redis session storage use case example

Example of using Redis for session storage: async function createSession(userId, data) { const sessionId = crypto.randomUUID(); const key = `session:${sessionId}`; await redis.hmset(key, ['userId', userId.toString(), 'created', Date.now().toString(), 'data', JSON.stringify(data)]); await redis.expire(key, 86400); return sessionId; } async function getSession(sessionId) { const key = `session:${sessionId}`; const exists = await redis.exists(key); if (!exists) return null; const [userId, created, data] = await redis.hmget(key, ['userId', 'created', 'data']); return { userId: Number(userId), created: Number(created), data: JSON.parse(data), }; }

Redis error handling example

Example of handling Redis errors: try { await redis.get('non-existent-key'); } catch (error) { if (error.code === 'ERR_REDIS_CONNECTION_CLOSED') { console.error('Connection to Redis server was closed'); } else if (error.code === 'ERR_REDIS_AUTHENTICATION_FAILED') { console.error('Authentication failed'); } else { console.error('Unexpected error:', error); } }

Redis implementation details

Bun's Redis client is implemented in Rust and uses the Redis Serialization Protocol (RESP3). It reconnects automatically with exponential backoff and pipelines commands, allowing multiple commands to be sent without waiting for replies to previous ones.

RedisClient constructor options

When creating a RedisClient, the following options can be passed in the second parameter: connectionTimeout (milliseconds, default 10000) sets connection timeout; idleTimeout (milliseconds, default 0 = no timeout) is counted from last data server sent, closing connection when fired without automatic reconnect; autoReconnect (boolean, default true) enables automatic reconnection on disconnection; maxRetries (number, default 20) sets maximum reconnection attempts; enableOfflineQueue (boolean, default true) queues commands when disconnected; enableAutoPipelining (boolean, default true) enables automatic command pipelining; tls (boolean or object, default false) enables TLS with optional custom config (rejectUnauthorized, ca, cert, key).

Redis limitations and future plans

Current limitations in Bun's Redis client: Transactions (MULTI/EXEC) require raw commands. Unsupported features: Redis Sentinel, Redis Cluster.

Redis client supported server versions

Bun's Redis client supports Redis server versions 7.2 and up.

Import Redis from bun

The Redis client is imported from the 'bun' module: import { redis, RedisClient } from 'bun';

Default Redis client environment variables

The default Redis client reads connection information from environment variables in this order of precedence: REDIS_URL, VALKEY_URL. If neither is set, it defaults to 'redis://localhost:6379'.

Redis client connection lifecycle

The Redis client automatically handles connections in the background. No connection is made until a command is executed. The first command initiates the connection, which remains open for subsequent commands. The connection can be explicitly closed with client.close().

Redis string operations

String operations include: set(key, value), get(key), getBuffer(key) returns Uint8Array, del(key), exists(key) returns boolean, expire(key, seconds) sets expiration, ttl(key) returns time to live in seconds.

Redis numeric operations

Numeric operations include: incr(key) increments by 1, decr(key) decrements by 1.

Redis hash operations

Hash operations include: hmset(key, array) sets multiple fields in a hash, hmget(key, array) gets multiple fields returning an array, hget(key, field) gets single field returning value directly or null if missing, hincrby(key, field, amount) increments numeric field, hincrbyfloat(key, field, amount) increments float field.

Redis set operations

Set operations include: sadd(key, member) adds member to set, srem(key, member) removes member from set, sismember(key, member) checks if member exists returning boolean, smembers(key) gets all members, srandmember(key) gets random member, spop(key) removes and returns random member.

Redis Pub/Sub basic usage

Redis Pub/Sub is available as native bindings added in Bun 1.2.23 and is experimental. Use client.publish(channelName, message) to publish messages. Use client.subscribe(channel, (message, channel) => {}) to subscribe to channels. Use client.unsubscribe() to unsubscribe from all channels, client.unsubscribe(channel) to unsubscribe from particular channel, or client.unsubscribe(channel, listener) to unsubscribe a particular listener.

Redis subscription connection limitation

Subscribing takes over the RedisClient connection. A client with subscriptions can only call subscription methods (subscribe(), psubscribe(), unsubscribe(), punsubscribe()), pubsub(), and ping(). To send other commands to Redis, create a separate connection with .duplicate().

Redis command pipelining

The client automatically pipelines commands by default, sending multiple commands in a batch and processing responses as they arrive. Automatic pipelining can be disabled by setting the enableAutoPipelining option to false when creating the client.

Redis send method for raw commands

Use the send(commandName, argsArray) method to run any Redis command, including ones without a dedicated method. The first argument is the command name as a string, and the second is an array of string arguments.

Redis connection event handlers

Register handlers for connection events: client.onconnect is called when successfully connected to Redis server; client.onclose(error) is called when disconnected from Redis server.

Redis connection status properties

Client connection properties include: client.connected returns a boolean indicating connection status; client.bufferedAmount returns the amount of data buffered in bytes.

Redis type conversion rules

The client automatically converts Redis responses: Integer responses become JavaScript numbers; Bulk strings become JavaScript strings; Simple strings become JavaScript strings; Null bulk strings and null arrays become null; Array responses become JavaScript arrays; Big number responses (RESP3) become BigInt, or string if not an integer literal; getBuffer returns payload as Buffer; Error responses throw JavaScript errors with error codes; Boolean responses (RESP3) become JavaScript booleans; Map responses (RESP3) become JavaScript objects; Set responses (RESP3) become JavaScript arrays. Special handling: EXISTS returns boolean (1 becomes true, 0 becomes false); SISMEMBER returns boolean (1 becomes true, 0 becomes false).

Redis commands that disable automatic pipelining

The following commands disable automatic pipelining: AUTH, INFO, QUIT, EXEC, MULTI, WATCH, SCRIPT, SELECT, CLUSTER, DISCARD, UNWATCH, PIPELINE, SUBSCRIBE, PSUBSCRIBE, UNSUBSCRIBE, UNPSUBSCRIBE.

Redis reconnection behavior

When a connection is lost, the client automatically attempts to reconnect with exponential backoff: starts with 50ms delay and doubles with each attempt, capped at 2000ms (2 seconds), attempts up to maxRetries times (default 20). While disconnected, the client queues commands if enableOfflineQueue is true (default) or rejects commands immediately if false.

Redis supported URL formats

The Redis client supports: standard redis://localhost:6379, redis://username:password@localhost:6379 with authentication, redis://localhost:6379/0 with database number, rediss://localhost:6379 and redis+tls://localhost:6379 for TLS connections, redis+unix:///path/to/socket for Unix socket connections, redis+tls+unix:///path/to/socket for TLS over Unix socket.

Redis error codes

Common error codes thrown by the Redis client: ERR_REDIS_CONNECTION_CLOSED indicates connection to server was closed; ERR_REDIS_AUTHENTICATION_FAILED indicates failed authentication with server; ERR_REDIS_INVALID_RESPONSE indicates received invalid response from server.

Redis basic operations example

Example showing basic Redis operations: const greeting = await redis.set('greeting', 'Hello from Bun!'); const result = await redis.get('greeting'); await redis.set('counter', 0); await redis.incr('counter'); const exists = await redis.exists('greeting'); await redis.del('greeting');

Redis custom client creation example

Example of creating a custom Redis client with connection URL: const client = new RedisClient('redis://username:password@localhost:6379'); await client.set('counter', '0'); await client.incr('counter');

Redis connection lifecycle control example

Example showing manual connection lifecycle control: const client = new RedisClient(); await client.connect(); await client.set('key', 'value'); client.close();

Give your agent this brain