# Rate Limiting Information

The `limit-count` plugin records each evaluation in the `$rate_limiting_info` variable. Other supported rate-limiting plugins can also populate this variable. Its value is an empty string before a supported rate-limiting plugin runs.

The expanded window diagnostics were introduced in APISIX 3.20.0 and API7 Enterprise 3.10.8. Earlier releases expose only the counter key, quota, remaining quota, and reset time.

## Use the Variable[​](#use-the-variable "Direct link to Use the Variable")

Add `$rate_limiting_info` to an access-log format or a logger plugin's `log_format` to record the evaluation result.

Fields are not emitted in a fixed order. Parse the value as JSON and read fields by name. The default NGINX log escaping represents quotation marks as `\x22`, so decode the log field before parsing it. Logger plugins can apply their own JSON escaping.

## Example[​](#example "Direct link to Example")

A local fixed-window request produces a decoded value similar to the following:

```
{

  "rate_limiting_key": "/apisix/routes/limit-route:1:example.com",

  "rate_limiting_limit": 100,

  "rate_limiting_remaining": 99,

  "rate_limiting_reset": 14,

  "window_type": "fixed",

  "window_size_ms": 60000,

  "decision": "allowed",

  "cost": 1,

  "evaluated_at_ms": 1759212345678,

  "current_window": {

    "start_ms": 1759212300123,

    "end_ms": 1759212360123,

    "count": 1,

    "created": true

  }

}
```

## Fields[​](#fields "Direct link to Fields")

| Field                                                                               | Description                                                                                                                                                       |
| ----------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `rate_limiting_key`                                                                 | Effective counter key. Treat it as an implementation value, not as a stable segmented format.                                                                     |
| `rate_limiting_limit`, `rate_limiting_remaining`                                    | Applied quota and remaining quota after the request.                                                                                                              |
| `rate_limiting_reset`                                                               | Seconds until the counter resets. For a rejected sliding-window request, this can be earlier than the end of the current window.                                  |
| `window_type`, `window_size_ms`                                                     | Window algorithm (`fixed` or `sliding`) and configured `time_window` in milliseconds.                                                                             |
| `decision`                                                                          | `allowed`, `rejected`, or `error`. An error result retains the four `rate_limiting_*` fields, `window_type`, and `window_size_ms`; it omits the remaining fields. |
| `cost`                                                                              | Amount added by the request.                                                                                                                                      |
| `evaluated_at_ms`                                                                   | Evaluation time as a Unix timestamp in milliseconds from the gateway clock.                                                                                       |
| `current_window.start_ms`, `current_window.end_ms`                                  | Current window boundaries as Unix timestamps in milliseconds.                                                                                                     |
| `current_window.count`                                                              | Count after the request, including its cost. It is `null` when a local fixed window rejects the request.                                                          |
| `current_window.created`                                                            | Fixed windows only. `true` for the request that created a local window and `null` for Redis policies.                                                             |
| `current_window.id`                                                                 | Sliding windows only. Clock-aligned window identifier.                                                                                                            |
| `previous_window.count`, `previous_window.weight`, `previous_window.weighted_count` | Sliding windows only. Previous count, the portion that remains in the sliding range, and the weighted count.                                                      |

A field that does not apply to the window type or configuration is omitted. A field that applies but is unknown is `null`.

## Window Behavior[​](#window-behavior "Direct link to Window Behavior")

A fixed window starts with the first request counted for a key. For Redis policies, the window boundary is derived from the counter TTL. A sliding window is clock-aligned and combines the current count with the weighted previous count.

The `cost` field is the amount added by the request. Fixed windows count rejected requests. Sliding windows and delayed synchronization count only allowed requests, so a rejected request has a cost of `0`.

## Delayed Synchronization[​](#delayed-synchronization "Direct link to Delayed Synchronization")

When a Redis policy uses `sync_interval`, the result includes the snapshot used to evaluate the request:

| Field                       | Description                                                 |
| --------------------------- | ----------------------------------------------------------- |
| `delayed_sync.synced_at_ms` | Time when the gateway instance last read the Redis counter. |
| `delayed_sync.synced_count` | Redis count at that time.                                   |
| `delayed_sync.local_delta`  | Pending local increment before this request.                |

`current_window.count` is an estimate based on the last Redis snapshot and local increments. It does not include increments that other gateway instances have not synchronized.

Each synchronization replaces the snapshot, and an expired snapshot is refreshed at the end of its window. A request after a boundary but before the next synchronization can therefore have an `evaluated_at_ms` later than `current_window.end_ms`.

## Multiple Rules[​](#multiple-rules "Direct link to Multiple Rules")

When `rules` contains multiple entries, the variable describes the rejecting rule, or the last rule evaluated when none rejects the request.

See [Limit Count Configuration](https://docs.api7.ai/hub/limit-count/configuration.md) for the plugin fields that control the window algorithm, quota, and synchronization policy.
