YAML Source is the Network Storage authoring standard.
Use the s&box Library Manager install for auto-updates. GitHub is best for agents, source review, contributions, and manual installs.

Rate Limits

Rate limit rules in v3 are defined at the project level as named rules. Each rule targets a specific collection and field (or uses wildcards), applies to a time...

# Rate Limits

Rate limit rules in v3 are defined at the project level as named rules. Each rule targets a specific collection and field (or uses wildcards), applies to a time window, and takes action when the limit is exceeded.

Project-level rate limits are managed from the dashboard and automatically enforced inside endpoint write steps.

## Defining Rules

Each rule has:

| Property | Description |
|----------|-------------|
| `name` | Unique identifier for this rule (e.g. `xp_daily_cap`) |
| `collection` | Target collection name, or `*` for all collections |
| `field` | Target field name, or `*` for all fields |
| `scope` | `per_player` or `global` |
| `window` | Time window for the limit |
| `limit` | Maximum allowed value within the window |
| `action` | What happens when exceeded: `reject`, `clamp`, or `flag` |

### Example rule

```yml
name: xp_daily_cap
collection: player_data
field: xp
scope: per_player
window: perDay
limit: 10000
action: reject
```

This rule means: each player can gain at most 10,000 XP per day across all endpoint calls. If an endpoint write step would push a player past the limit, the request is rejected.

## Scope

### per_player

The limit is tracked independently for each player (by Steam ID). Player A and Player B each get their own 10,000 XP daily allowance.

Use `per_player` for most gameplay limits -- XP caps, gold earning rates, purchase frequency.

### global

The limit is tracked across all players combined. Useful for limiting total currency entering the economy or capping global event participation.

```yml
name: event_gold_pool
collection: player_data
field: gold
scope: global
window: perDay
limit: 5000000
action: clamp
```

This caps total gold generated by all players to 5 million per day. Once hit, any endpoint that awards gold will have the amount clamped to zero.

## Time Windows

| Window | Duration |
|--------|----------|
| `perMinute` | 60 seconds |
| `perHour` | 3,600 seconds |
| `perDay` | 86,400 seconds |
| `perWeek` | 604,800 seconds |
| `perMonth` | 2,592,000 seconds (30 days) |
| `perYear` | 31,536,000 seconds (365 days) |

You can define multiple rules for the same field with different windows:

```yml
- name: gold_hourly
collection: player_data
field: gold
scope: per_player
window: perHour
limit: 50000
action: clamp
- name: gold_daily
collection: player_data
field: gold
scope: per_player
window: perDay
limit: 500000
action: reject
```

A player can earn up to 50,000 gold per hour (clamped if exceeded) and up to 500,000 gold per day (rejected if exceeded). The hourly limit uses `clamp` for a soft cap, while the daily limit uses `reject` as a hard stop.

## Actions

### reject

Stops the endpoint pipeline and returns an error. No data is written.

```yml
ok: false
error: RATE_LIMITED
rule: xp_daily_cap
limit: 10000
used: 9800
remaining: 200
requested: 500
resetIn: 14400
```

The response includes how much capacity remains and when the window resets (in seconds). Use `resetIn` to show the player when they can try again.

### clamp

Adjusts the value down to whatever capacity remains. The pipeline continues with the reduced amount.

If a player has used 9,800 of their 10,000 XP daily cap and an endpoint tries to award 500 XP, the system clamps the award to 200 XP and continues. The response includes the actual amount awarded.

Clamping is transparent to the endpoint pipeline -- subsequent steps see the clamped value. Use clamp for soft caps where you want the action to succeed with a reduced reward.

### flag

Allows the write to proceed but flags the player for review. The flag includes the rule name, the amount that exceeded the limit, and the endpoint context.

Use `flag` for soft limits where you want to monitor behavior without blocking players. Combine with `reject` or `clamp` on stricter windows.

```yml
name: suspicious_gold_gain
collection: player_data
field: gold
scope: per_player
window: perHour
limit: 100000
action: flag
```

## Automatic Enforcement in Endpoints

Rate limits are enforced automatically on every `write` step in your endpoints. You do not need to add condition steps to check limits manually.

When a write step executes:

1. The system identifies all rate limit rules matching the target collection and fields
2. For each matching rule, it checks the player's (or global) usage in the current window
3. If any rule is exceeded, the configured action fires
4. If the action is `reject`, the pipeline stops and no data is written
5. If the action is `clamp`, the value is reduced and the pipeline continues
6. If the action is `flag`, the write proceeds and a flag is recorded

Multiple rules can match a single write. They are evaluated in order: `reject` rules are checked first, then `clamp`, then `flag`. If any reject rule fires, the pipeline stops immediately.

## Bypass Conditions

Sometimes specific write steps should skip certain rate limits. For example, an admin-grant endpoint should not be capped by the XP daily limit.

Add `bypassRules` to a write step to skip named rules:

```yml
id: admin_grant
type: write
collection: player_data
key: "{{steamId}}"
bypassRules:
- xp_daily_cap
- gold_hourly
ops:
- op: inc
path: xp
value: "{{input.amount}}"
source: admin_grant
reason: Manual grant by admin
```

Only use `bypassRules` on endpoints that are properly gated (e.g. with an admin role workflow). An ungated endpoint with bypass rules is a security hole.

## Wildcard Rules

Use `*` for collection or field to create broad rules:

```yml
name: global_write_throttle
collection: "*"
field: "*"
scope: per_player
window: perMinute
limit: 60
action: reject
```

This limits each player to 60 total write operations per minute across all collections and fields. Useful as a baseline anti-abuse measure.

Specific rules take priority over wildcard rules. If a field matches both a specific rule and a wildcard rule, both are evaluated.

## Presets

Common rate limit configurations you can use as starting points:

### Save throttle

Prevents rapid-fire saves from spamming your database.

```yml
name: save_throttle
collection: "*"
field: "*"
scope: per_player
window: perMinute
limit: 30
action: reject
```

### XP daily cap

Caps how much XP a player can earn per day. Prevents grinding exploits.

```yml
name: xp_daily_cap
collection: player_data
field: xp
scope: per_player
window: perDay
limit: 10000
action: clamp
```

### Currency cap

Hard limit on currency earning rate. Rejects once exceeded.

```yml
name: gold_daily_cap
collection: player_data
field: gold
scope: per_player
window: perDay
limit: 500000
action: reject
```

### Suspicious activity monitor

Flags players who earn unusually fast, without blocking them.

```yml
name: suspicious_xp_rate
collection: player_data
field: xp
scope: per_player
window: perHour
limit: 5000
action: flag
```

## C# Example: Handling Rate Limit Errors

```csharp
var response = await NetworkStorage.CallEndpoint( "report-kill", new
{
target = "training_dummy"
} );

if ( !response.HasValue )
{
// The library logs endpoint errors such as rate-limit rejections.
Log.Warning( "Reward was not applied. Try again later." );
return;
}

// Success -- update local state
var xp = response.Value.Int( "xp", 0 );
var gold = response.Value.Int( "gold", 0 );
var level = response.Value.Int( "level", 1 );
Log.Info( $"Kill rewarded! XP: {xp}, Gold: {gold}, Level: {level}" );
```