> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pecta.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# RTB tmax guard: skip stale bid evaluations

> Skips all downstream gates when the OpenRTB tmax deadline budget is nearly exhausted, preventing wasted work on bids that are already too late.

The tmax guard checks how much time remains in the OpenRTB `tmax` window before running any other gate. If the remaining budget falls below a configurable threshold, it returns `skipped: true` and — because the engine runs fail-fast — all subsequent gates are bypassed. This keeps your gate pipeline from doing meaningful work on a bid that has already missed its serve deadline.

## Usage

```typescript theme={null}
import { createEngine, gates } from "@pecta/core";

const engine = createEngine({
  gates: [
    gates.rtb.tmaxGuard({ bufferMs: 15 }),
    // ... other RTB gates
  ],
  timeout: 15,
});
```

<Note>
  Place `tmaxGuard` first in every RTB gate list. It is the only gate designed to short-circuit the entire pipeline on deadline exhaustion.
</Note>

## Options

<ParamField path="bufferMs" type="number" default="15">
  The minimum number of milliseconds that must remain in the `tmax` window for downstream gates to run. If the remaining budget is less than this value, the gate returns `skipped: true`. Defaults to `15`.
</ParamField>

<ParamField path="name" type="string" default="rtb.tmax-guard">
  Override the gate's name in evaluation results and telemetry.
</ParamField>

## Required context fields

The gate reads two fields from `EvaluationContext`. If either is absent, the gate passes through silently — it cannot enforce a deadline it cannot measure.

```typescript theme={null}
const result = await engine.evaluate({
  agent_id: "dsp-bidder-prod",
  input: openRtbRequest,
  output: openRtbResponse,
  tmaxMs: openRtbRequest.tmax,   // OpenRTB tmax in milliseconds
  startedAt: requestStartMs,     // Date.now() when the request arrived
});
```

The gate computes elapsed time as `Date.now() - startedAt` at the moment it runs, then checks whether `tmaxMs - elapsed < bufferMs`.

## What "skipped" means

A `skipped` result is **not a failure**. The gate result looks like this:

```json theme={null}
{
  "name": "rtb.tmax-guard",
  "passed": true,
  "skipped": true,
  "reason": "tmax budget exhausted (8ms < 15ms buffer)",
  "latency_ms": 0
}
```

Skipped gates do not penalise the agent's reputation score. They signal that evaluation was intentionally bypassed, not that a problem was found.

<Tip>
  Set `bufferMs` to match your engine's `timeout` option. If your gate pipeline has a 15ms budget, a `bufferMs` of 15 ensures you never start evaluating a bid that cannot complete before the auction closes.
</Tip>

## When context fields are missing

If `tmaxMs` or `startedAt` is not a number on the context, the gate returns:

```json theme={null}
{
  "name": "rtb.tmax-guard",
  "passed": true,
  "skipped": true,
  "reason": "tmax/startedAt unavailable"
}
```

No error is thrown. The remaining gates run normally.

<Warning>
  If you omit `startedAt` from the context, the tmax guard cannot protect you from deadline overruns. Always record `Date.now()` at the point the upstream bid request is received and pass it as `startedAt`.
</Warning>
