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

# Reliability & serverless

> The fail-open guarantees of @glassray/tracing, the documented queue and retry bounds, and what each serverless platform needs.

The SDK's contract is **fail-open, always**: if Glassray is down, slow, or misconfigured - or the SDK itself has a bug - the worst case is lost telemetry. Your agent is never blocked, never slowed on the critical path, and never crashed by tracing.

## The guarantees

* Every public method is internally guarded; SDK errors go to a rate-limited warning (or your `onWarn`), and your return value or exception passes through untouched.
* A missing or invalid API key disables sending, not your agent.
* No timer or socket ever holds the process open - everything is `unref`'d.
* Invalid configuration warns and disables; it never throws.
* The SDK sends nothing but your traces - zero phone-home.

## Delivery model

A trace is buffered in memory while it runs and **POSTed once, when its root settles** - on success or on throw. One trace, one request, off the critical path. This matches the ingest contract (whole trace per request - see [Bring your own OTel](/sdk-byo-otel) for why that matters).

## The bounds

Documented because the numbers are the trust signal - this is exactly how much memory, time, and retry traffic the SDK will ever cost you:

| Bound           | Value                                                                                                   |
| --------------- | ------------------------------------------------------------------------------------------------------- |
| Outbound queue  | **100 traces / 20 MiB** - overflow drops the oldest trace and warns once                                |
| Request timeout | **10 s**                                                                                                |
| Compression     | gzip for payloads ≥ **8 KiB**                                                                           |
| `429`           | Honors `Retry-After`, pauses the sender for the window                                                  |
| `503` / network | Jittered backoff, max **2** retries                                                                     |
| Other 4xx       | Dropped immediately - retrying client errors only amplifies outages                                     |
| `401` / `403`   | Warn once, then mute the sender (fix the key, restart)                                                  |
| Per-field cap   | **32 KiB** per content attribute - truncated with an explicit `…[glassray:truncated N bytes]` marker    |
| Whole-trace cap | **4 MiB** soft cap - largest span contents truncate first; structure, timing, and tokens always survive |

Everything dropped is accounted for:

```ts theme={null}
glassray.stats(); // { sent, dropped: { byReason }, queued }
```

## Serverless

Because a trace POSTs at root settle, a long-lived process needs nothing. Platforms that freeze or kill the process right after the response need one flush call:

| Runtime                          | What you need                                                                                                         |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| Long-lived Node (server, worker) | Nothing.                                                                                                              |
| Vercel                           | `waitUntil(glassray.flush())` after the response.                                                                     |
| AWS Lambda                       | `await glassray.flush()` before returning from the handler.                                                           |
| Cloudflare Workers               | `ctx.waitUntil(glassray.flush())` - needs the `nodejs_compat` flag; edge runtimes are early, Node is the tested path. |

```ts theme={null}
// Vercel route handler
import { waitUntil } from "@vercel/functions";

export const POST = async (req: Request) => {
  const result = await glassray.trace("handle-request", async (t) => runAgent(req, t));
  waitUntil(glassray.flush());
  return Response.json(result);
};
```

<Tip>
  Traces cut off mid-run or missing entirely on serverless is almost always a missing flush - it's the first item on the [troubleshooting checklist](/sdk-troubleshooting).
</Tip>
