# How to Configure Xray-core Policy Settings for Timeouts, Stats, and Buffer Sizes

> Learn to configure Xray-core policy settings for timeouts, stats, and buffer sizes within your config file. Optimize performance by overriding default values for enhanced control.

- Repository: [Project X Community, Not Porn-jet X Hub/Xray-core](https://github.com/XTLS/Xray-core)
- Tags: how-to-guide
- Published: 2026-04-21

---

**You configure Xray-core policy settings through the `policy` section of your JSON, YAML, or TOML configuration file, defining per-level timeouts, statistics collection, and buffer allocations that override the internal defaults defined in [`features/policy/policy.go`](https://github.com/XTLS/Xray-core/blob/main/features/policy/policy.go).**

The Xray-core proxy platform uses a **policy manager** to enforce connection handling rules, traffic accounting, and memory management. These policies are defined in the `app/policy` package and loaded at startup from your main configuration file. Understanding how to tune these settings allows you to optimize performance for high-throughput scenarios, reduce memory footprint on resource-constrained systems, and enable detailed traffic monitoring.

## Policy Configuration Structure

The policy configuration consists of two main branches: **level-specific policies** (`policy.level`) that apply to individual users by their level ID, and **system policies** (`policy.system`) that apply globally across all inbound and outbound handlers.

### Timeout Settings

The `policy.timeout` section controls how long Xray-core waits during various connection phases. These values are defined as seconds in the configuration, then converted to Go `time.Duration` values internally via the `Second.Duration()` helper in [`app/policy/config.go`](https://github.com/XTLS/Xray-core/blob/main/app/policy/config.go).

| Timeout Field | Purpose | Default Value |
|-------------|---------|-------------|
| `handshake` | Time to complete TLS/WS handshake | 60 seconds |
| `connection_idle` | Time to keep idle connection alive | 300 seconds |
| `uplink_only` | Grace period after client closes write | 1 second |
| `downlink_only` | Grace period after server closes write | 1 second |

These defaults are hardcoded in [`features/policy/policy.go`](https://github.com/XTLS/Xray-core/blob/main/features/policy/policy.go) and can be overridden per user level.

### Stats Settings

The `policy.stats` section enables **per-user traffic accounting** and online tracking. When enabled, Xray-core maintains counters in memory that can be queried via the Stats API or logged for analysis.

| Stat Field | When Enabled |
|-----------|-------------|
| `user_uplink` | Tracks bytes sent by the user (client → proxy) |
| `user_downlink` | Tracks bytes received by the user (proxy → client) |
| `user_online` | Maintains a map of currently active connections per user |

System-level stats are configured separately under `policy.system.stats` and apply to all inbound/outbound handlers regardless of user level.

### Buffer Settings

The `policy.buffer` section controls **per-connection memory allocation**. This is particularly important for high-throughput proxies where default buffer sizing may create bottlenecks or excessive memory pressure.

| Buffer Field | Description |
|-----------|-------------|
| `connection` | Bytes to allocate per connection. `-1` means unlimited. |

The default buffer size is determined at runtime in [`features/policy/policy.go`](https://github.com/XTLS/Xray-core/blob/main/features/policy/policy.go) based on:
- The `XrayBufferSize` environment variable (value in MiB)
- CPU architecture detection (some architectures receive larger default buffers)

When `XrayBufferSize=0`, the pipe transport uses unlimited buffering (`-1`), which can improve throughput at the cost of unbounded memory growth during backpressure.

## Loading Policy Configuration

The policy manager follows a specific lifecycle from configuration to runtime enforcement:

1. **Configuration parsing** – Your JSON/YAML/TOML is unmarshaled into `app/policy.Config` (generated from `config.proto`)

2. **Default overlay** – [`app/policy/config.go`](https://github.com/XTLS/Xray-core/blob/main/app/policy/config.go) defines `defaultPolicy()` which establishes baseline values for any unspecified fields

3. **Manager instantiation** – `app/policy.New` creates a `policy.Instance` storing level→Policy mappings

4. **Runtime lookup** – Proxy handlers call `policyManager.ForLevel(user.Level)` to obtain a `policy.Session` with resolved timeouts, stats flags, and buffer settings

5. **Context injection** – `policy.ContextWithBufferPolicy` embeds buffer settings into the request context for transport layers

6. **Transport consumption** – [`transport/pipe/pipe.go`](https://github.com/XTLS/Xray-core/blob/main/transport/pipe/pipe.go) extracts and applies the buffer policy when creating data pipes

## Practical Configuration Examples

### Minimal JSON Configuration

This example configures a level-1 user with tightened timeouts, full stats collection, and a 1KB buffer limit:

```json
{
  "policy": {
    "level": {
      "1": {
        "timeout": {
          "handshake": { "value": 30 },
          "connection_idle": { "value": 120 },
          "uplink_only": { "value": 5 },
          "downlink_only": { "value": 5 }
        },
        "stats": {
          "user_uplink": true,
          "user_downlink": true,
          "user_online": true
        },
        "buffer": {
          "connection": 1024
        }
      }
    },
    "system": {
      "stats": {
        "inbound_uplink": true,
        "inbound_downlink": true,
        "outbound_uplink": true,
        "outbound_downlink": true
      }
    }
  }
}

```

### Equivalent YAML Configuration

YAML offers cleaner syntax for the same policy structure:

```yaml
policy:
  level:
    "1":
      timeout:
        handshake: { value: 30 }
        connection_idle: { value: 120 }
        uplink_only: { value: 5 }
        downlink_only: { value: 5 }
      stats:
        user_uplink: true
        user_downlink: true
        user_online: true
      buffer:
        connection: 1024  # 1 KB

  system:
    stats:
      inbound_uplink: true
      inbound_downlink: true
      outbound_uplink: true
      outbound_downlink: true

```

### Environment Variable Buffer Override

For system-wide buffer tuning without modifying configuration files:

```bash

# Set 2 MiB buffers for all connections

export XrayBufferSize=2
./xray -c config.json

# Disable buffer limits entirely (unlimited mode)

export XrayBufferSize=0
./xray -c config.json

```

The `XrayBufferSize` value is parsed in [`features/policy/policy.go`](https://github.com/XTLS/Xray-core/blob/main/features/policy/policy.go) and converted to bytes for the per-connection buffer allocation.

## Code-Level Policy Integration

Proxy handlers integrate with the policy manager through the standard interface defined in [`app/policy/manager.go`](https://github.com/XTLS/Xray-core/blob/main/app/policy/manager.go). Here's how the VLESS inbound handler (excerpted from [`proxy/vless/inbound/inbound.go`](https://github.com/XTLS/Xray-core/blob/main/proxy/vless/inbound/inbound.go)) obtains and applies policy settings:

```go
func (h *Handler) handleConnection(ctx context.Context, request *vless.Request) error {
    // Acquire policy manager from core instance
    pm := h.policyManager
    
    // Resolve session policy for this user's level
    sess := pm.ForLevel(request.User.Level)
    
    // Inject buffer policy into context for transport layer
    ctx = policy.ContextWithBufferPolicy(ctx, sess.Buffer)
    
    // Apply handshake timeout from policy
    conn.SetDeadline(time.Now().Add(sess.Timeouts.Handshake))
    
    // Check if user stats should be recorded
    if sess.Stats.UserUplink {
        // Record uplink traffic...
    }
    
    // Continue with connection handling...
}

```

Key integration points:

- `pm.ForLevel()` returns a `policy.Session` from [`features/policy/policy.go`](https://github.com/XTLS/Xray-core/blob/main/features/policy/policy.go)
- `policy.ContextWithBufferPolicy()` stores buffer settings in the request context
- The pipe transport ([`transport/pipe/pipe.go`](https://github.com/XTLS/Xray-core/blob/main/transport/pipe/pipe.go)) retrieves these settings via `policy.BufferPolicyFromContext()`

## Summary

- **Xray-core policy settings** are configured through the `policy` section of your main configuration file, supporting JSON, YAML, and TOML formats.

- **Timeout policies** control handshake (default 60s), idle connection (default 300s), and uplink/downlink-only periods (default 1s), defined in [`features/policy/policy.go`](https://github.com/XTLS/Xray-core/blob/main/features/policy/policy.go).

- **Stats policies** enable per-user traffic counters (`user_uplink`, `user_downlink`) and online tracking (`user_online`), plus system-wide inbound/outbound statistics.

- **Buffer policies** set per-connection memory allocation via `policy.buffer.connection` or the `XrayBufferSize` environment variable, with `-1` or `0` enabling unlimited mode.

- **Implementation files** include `app/policy/config.proto` (schema), [`app/policy/config.go`](https://github.com/XTLS/Xray-core/blob/main/app/policy/config.go) (defaults), [`app/policy/manager.go`](https://github.com/XTLS/Xray-core/blob/main/app/policy/manager.go) (lookup), and [`features/policy/policy.go`](https://github.com/XTLS/Xray-core/blob/main/features/policy/policy.go) (runtime structures).

## Frequently Asked Questions

### How do I enable unlimited buffer sizes in Xray-core?

Set the `XrayBufferSize` environment variable to `0` before starting Xray-core, or configure `policy.buffer.connection: -1` for a specific user level. According to [`features/policy/policy.go`](https://github.com/XTLS/Xray-core/blob/main/features/policy/policy.go), both values trigger unlimited buffer allocation in the pipe transport ([`transport/pipe/pipe.go`](https://github.com/XTLS/Xray-core/blob/main/transport/pipe/pipe.go)), which removes backpressure limits but may cause unbounded memory growth during traffic spikes.

### What's the difference between user-level and system-level stats?

User-level stats (`policy.level.*.stats`) track per-user traffic and connection state, requiring each user to have a defined level ID in your authentication configuration. System-level stats (`policy.system.stats`) apply globally to all inbound and outbound handlers regardless of user identity, as defined in `app/policy/config.proto`. Enable both when you need granular per-user accounting plus aggregate infrastructure monitoring.

### Why are my timeout changes not taking effect?

Verify that your user accounts reference the correct level ID matching your `policy.level` configuration. The policy manager ([`app/policy/manager.go`](https://github.com/XTLS/Xray-core/blob/main/app/policy/manager.go)) resolves settings via `ForLevel(user.Level)`, so a mismatch between the user's assigned level and your policy keys causes fallback to defaults from `defaultPolicy()` in [`app/policy/config.go`](https://github.com/XTLS/Xray-core/blob/main/app/policy/config.go). Also confirm that timeout values are specified as objects with a `value` field (e.g., `{"value": 30}`), not bare integers.