# Limits

> Source: `src/content/docs/actors/limits.mdx`
> Canonical URL: https://rivet.dev/docs/actors/limits
> Description: Limits and constraints for Rivet Actors.

---
This page documents the limits for Rivet Actors.

There are two types of limits:

- **Soft Limit**: Application-level limit, configurable in RivetKit. These cannot exceed the hard limit.
- **Hard Limit**: Infrastructure-level limit that cannot be configured.

Soft limits are configured in two places. Registry-level WebSocket message-size limits are passed to `setup`:

Per-actor limits such as queue sizes and lifecycle timeouts are passed to `actor(...)` via `options`:

## Limits

### WebSocket

These limits affect actions that use `.connect()` and [low-level WebSockets](/docs/actors/websocket-handler).

| Name | Soft Limit | Hard Limit | Description |
|------|------------|------------|-------------|
| Max incoming message size | 64 KiB | 32 MiB | Maximum size of incoming WebSocket messages. Soft limit configurable via `maxIncomingMessageSize`; hard limit configurable in self-hosted engine config via `guard.websocket_max_message_size`. |
| Max outgoing message size | 1 MiB | 32 MiB | Maximum size of outgoing WebSocket messages. Soft limit configurable via `maxOutgoingMessageSize`; hard limit configurable in self-hosted engine config via `guard.websocket_max_message_size`. |
| Max WebSocket frame size | — | 32 MiB | Maximum size of a single WebSocket frame accepted by Rivet's transport edge. Configurable in self-hosted engine config via `guard.websocket_max_frame_size`. This is not configurable by browser clients and is not negotiated during the WebSocket handshake. |
| WebSocket open timeout | — | 15 seconds | Time allowed for WebSocket connection to be established, including `onBeforeConnect` and `createConnState` hooks. Connection is closed if exceeded. |
| Message ack timeout | — | 30 seconds | Time allowed for message acknowledgment before connection is closed. Only relevant in the case of a network issue and does not affect your application. |

### Hibernating WebSocket

Hibernating WebSockets allow actors to sleep while keeping client connections alive. All WebSocket limits above also apply to hibernating WebSockets. See [WebSocket Hibernation](/docs/actors/websocket-handler#web-socket-hibernation) for details.

| Name | Soft Limit | Hard Limit | Description |
|------|------------|------------|-------------|
| Max pending buffer size | — | 128 MiB | Total size of all buffered messages per connection while actor is sleeping. |
| Max pending message count | — | 65,535 | Maximum number of buffered messages per connection while actor is sleeping. |
| Hibernation timeout | — | 90 seconds | Maximum time an actor has to wake up before the client is disconnected. Only relevant if something is wrong with starting actors. |

### HTTP

These limits affect actions that do not use `.connect()` and [low-level HTTP requests](/docs/actors/request-handler).

| Name | Soft Limit | Hard Limit | Description |
|------|------------|------------|-------------|
| Max request body size | — | 20 MiB | Maximum size of HTTP request bodies. |
| Max response body size | — | 20 MiB | Maximum size of HTTP response bodies. |
| Request timeout | 60 seconds | — | Maximum time for an `onRequest` handler to complete. Defaults to `actionTimeout`; configure with `actionTimeout`. |

### Networking

| Name | Soft Limit | Hard Limit | Description |
|------|------------|------------|-------------|
| Connection ping timeout | — | 30 seconds | Connection is closed if a ping is not acknowledged within this time. Applies to both HTTP and WebSocket. Only relevant in the case of a network issue and does not affect your application. |

### Queue

| Name | Soft Limit | Hard Limit | Description |
|------|------------|------------|-------------|
| Max queue size | 1,000 messages | — | Maximum number of messages in the queue before new messages are rejected. Configurable via `maxQueueSize`. |
| Max queue message size | 64 KiB | 128 KiB (effective) | Maximum size of each individual queue message. Configurable via `maxQueueMessageSize`. Actual payload is slightly lower after queue serialization overhead. |

### Actor KV Storage

These limits apply to the low-level KV storage interface powering Rivet Actors. They likely do not affect your application, but are documented for completeness.

| Name | Soft Limit | Hard Limit | Description |
|------|------------|------------|-------------|
| Max key size | — | 2 KiB | Maximum size of a single key. |
| Max value size | — | 128 KiB | Maximum size of a single value. |
| Max keys per operation | — | 128 | Maximum number of keys in a single batch get/put/delete operation. Does not apply to range operations (`listRange`, `deleteRange`). |
| Max batch put payload size | — | 976 KiB | Maximum total size of all key-value pairs in a single batch put operation. |
| Max storage size per actor | — | 10 GiB | Maximum total KV storage size for a single actor. |
| List default limit | — | 16,384 | Default maximum number of keys returned by a list operation. |

### Actor SQLite Storage

These limits apply to the [SQLite database](/docs/actors/state#sqlite-database) available via `this.sql`. SQLite data is stored through the KV layer, so the storage limit is shared with KV storage.

| Name | Soft Limit | Hard Limit | Description |
|------|------------|------------|-------------|
| Max storage size per actor | — | 10 GiB | Maximum total storage size for a single actor. This limit is shared with KV storage. |
| Max dirty data per commit | — | 1,310,720 bytes | Maximum raw SQLite page data that can be written in a single commit. This is 320 dirty pages at 4 KiB per page. |
| Transaction deadline | 60 seconds | — | Safety backstop for `db.transaction()`. Configure per transaction with `{ timeout: milliseconds }`; there is no product-level maximum. |
| Transaction coordinator queue | — | 128 operations | Maximum admitted SQLite operations waiting behind an active coordinated transaction. Additional operations fail with `sqlite.transaction_queue_full`. |

SQLite commit deltas are compressed and split into internal chunks before storage, but all chunks for one commit are published atomically. The commit limit is therefore based on raw dirty page bytes before compression, not the compressed delta size.

Avoid `VACUUM` inside actor databases. It rewrites the database in one transaction and can exceed the dirty-page commit limit even when ordinary incremental writes fit.

### Actor Runtime Socket

The Beta [Actor Runtime Socket](/docs/actors/actor-runtime-socket) negotiates its active frame limit during the handshake.

| Name | Soft Limit | Hard Limit | Description |
|------|------------|------------|-------------|
| Frame payload size | 32 MiB | — | Default maximum request or response payload. Self-hosted native runtimes can configure `RIVET_ACTOR_RUNTIME_SOCKET_MAX_FRAME_BYTES`; oversized responses return `ResponseTooLarge`. |

### KV Preloading

When an actor starts, the engine can pre-fetch KV data declared in the actor name metadata and deliver it alongside the start command. This removes round-trips to storage during actor startup. RivetKit emits the preload manifest from its own key layout and exposes per-actor overrides via `options`. Operators can still enforce a global cap in the [engine config](/docs/self-hosting/configuration) with `pegboard.preload_max_total_bytes`. In serverless mode, this data is serialized into the `/api/rivet/start` request body along with actor config and protocol metadata, so the accepted body size must be larger than the preload budget. RivetKit defaults `serverless.maxStartPayloadBytes` to 16 MiB to leave margin for the default 1 MiB preload budget and larger SQLite startup page preloads.

| Name | Soft Limit | Hard Limit | Description |
|------|------------|------------|-------------|
| Max total preload size | 1 MiB | — | Maximum total size of all preloaded KV data sent with the start command. Configurable via `pegboard.preload_max_total_bytes`. Setting to 0 disables all preloading. |
| Max workflow preload size | 128 KiB | — | Default maximum size of preloaded workflow data for RivetKit actors. Configurable per actor via `options.preloadMaxWorkflowBytes`. Setting to 0 disables workflow preloading for that actor. |
| Max connections preload size | 64 KiB | — | Default maximum size of preloaded connection data for RivetKit actors. Configurable per actor via `options.preloadMaxConnectionsBytes`. Setting to 0 disables connections preloading for that actor. |

### Actor Input

See [Actor Input](/docs/actors/input) for details.

| Name | Soft Limit | Hard Limit | Description |
|------|------------|------------|-------------|
| Max actor input size | — | 4 MiB | Maximum size of the input passed when creating an actor. |
| Max connection params size | — | 4 KiB | Maximum size of connection parameters passed when connecting to an actor. |
| Max actor key component size | — | 128 bytes | Maximum size of each component in an actor key array. |
| Max actor key total size | — | 1,024 bytes | Maximum total size of the serialized actor key string. |
| Max actor name length | — | 64 characters | Maximum length for actor and project identifiers. |

### Rate Limiting

| Name | Soft Limit | Hard Limit | Description |
|------|------------|------------|-------------|
| Rate limit | — | 1200 requests/minute | Default rate limit per actor per IP address with a 1 minute time bucket. |
| Max in-flight requests | — | 32 | Default maximum concurrent requests to an actor per IP address. |

### Timeouts

| Name | Soft Limit | Hard Limit | Description |
|------|------------|------------|-------------|
| Action timeout | 60 seconds | — | Timeout for RPC actions. Configurable via `actionTimeout`. |
| On request timeout | 60 seconds | — | Timeout for raw `onRequest` handlers. Defaults to `actionTimeout`; configure with `actionTimeout`. |
| On before connect timeout | 5 seconds | — | Timeout for the `onBeforeConnect` hook. Configurable via `onBeforeConnectTimeout`. |
| Create vars timeout | 5 seconds | — | Timeout for `createVars` hook. Configurable via `createVarsTimeout`. |
| Create conn state timeout | 5 seconds | — | Timeout for `createConnState` hook. Configurable via `createConnStateTimeout`. |
| On connect timeout | 5 seconds | — | Timeout for `onConnect` hook. Configurable via `onConnectTimeout`. |
| On migrate timeout | 30 seconds | — | Timeout for `onMigrate` hook. Configurable via `onMigrateTimeout`. |
| Sleep grace period | 15 seconds | — | Total graceful shutdown budget for both sleep and destroy. Covers `onSleep`/`onDestroy`, run handler shutdown, `waitUntil`, `keepAwake`, async raw WebSocket handlers, and connection cleanup. Configurable via `sleepGracePeriod`. |
| Sleep timeout | 30 seconds | — | Time of inactivity before actor hibernates. Configurable via `sleepTimeout`. |
| State save interval | 1 second | — | Interval between automatic state saves. Configurable via `stateSaveInterval`. |
| Connection liveness timeout | 2.5 seconds | — | Time a stateful connection can miss liveness checks before RivetKit treats it as unhealthy. Configurable via `connectionLivenessTimeout`. |
| Connection liveness interval | 5 seconds | — | Interval between stateful connection liveness checks. Configurable via `connectionLivenessInterval`. |

### Serverless Shutdown

These timeouts control how actors are shut down when a serverless request reaches its lifespan limit. See [Shutdown Sequence](/docs/general/runtime-modes#shutdown-sequence) for details.

| Name | Soft Limit | Hard Limit | Description |
|------|------------|------------|-------------|
| Request lifespan | 3600 seconds (60 min) | — | Total lifespan of a serverless request before drain begins. Configurable via `requestLifespan` in [`configurePool`](/docs/general/registry-configuration). |
| Runner config drain grace period | — | 30 minutes | Time a serverless runner reserves for actors to stop gracefully. Configurable via `drainGracePeriod` in [`configurePool`](/docs/general/registry-configuration). |
| Engine serverless drain fallback | — | 10 seconds | Engine-level fallback used when no per-runner config applies. Configurable via [engine config](/docs/self-hosting/configuration) (`pegboard.serverless_drain_grace_period`). |

### Actor Lifecycle

| Name | Soft Limit | Hard Limit | Description |
|------|------------|------------|-------------|
| Actor start threshold | — | 30 seconds | Maximum time for an actor to start before it is considered lost and rescheduled. |
| Actor stop threshold | — | 30 minutes | Maximum time for an actor to stop before it is considered lost. |

## Increasing Limits

These limits are sane defaults designed to protect your application from exploits and accidental runaway bugs. If you have a use case that requires different limits, [contact us](https://rivet.dev/contact) to discuss your requirements.

_Source doc path: /docs/actors/limits_
