TokenPolice
Docs
SDK reference

Flushing & serverless

flush vs flush_sync/flushSync, the serverless() wrapper, shutdown, and edge caveats.

TokenPolice ships /log telemetry in the background so it never slows your call. In a long-running server that's invisible. But when the process is about to stop — a serverless function freezing, a script exiting — you need to drain those pending logs first, or the last calls are lost.

The one asymmetry to remember

CallPythonNode
flush()await flush() — real drainawait tp.flush() — real drain
flush_sync / flushSyncflush_sync() — real blocking drainflushSync()diagnostic only, drains nothing

Both SDKs have a real drain. The trap is flushSync in Node: it can't block on a promise, so it does not drain — it's for diagnostics only. Node's real drain is always awaited.

# Python — either of these genuinely drains
import token_police as tp
tp.flush_sync()          # blocking, for sync code
# or:  await tp.flush()  # for async code
// Node — the real drain is awaited
import * as tp from "token-police";
await tp.flush();

Serverless

Set deployment="serverless" (or leave it "auto" — most platforms are detected). That switches internal behavior, but it does not flush for you. Two ways to drain before freeze:

Wrap the handler with serverless() — it drains in a finally:

import token_police as tp

@tp.serverless
async def handler(event, context):
    ...   # drained automatically on the way out

Or flush yourself in a finally:

export async function handler(event) {
  try {
    // ... your LLM calls
  } finally {
    await tp.flush();
  }
}

Node async handlers get a real drain from serverless() and from await tp.flush(). Node sync handlers can't await, so durability there comes from keepalive on the /log requests — the platform keeps them alive briefly after the handler returns.

Scripts and short-lived processes

A script that exits immediately can cut off in-flight logs — and in Node the open rule-stream can keep the event loop alive.

  • Python: call flush_sync() before exit. (Normal exits are also covered automatically.) Python has no shutdown()flush_sync() is the whole story.
  • Node: call await tp.shutdown() — it stops the stream and drains. Without it a short script may hang on the open connection. flushSync() is not a substitute: in Node it drains nothing.
await tp.shutdown();   // Node scripts/CLIs: stops the stream and drains

Edge runtimes

On edge runtimes (deployment="edge"), the underlying instrumentors can't load, so usage metering is limited to the providers TokenPolice taps manually. Enforcement still works — the pre-flight /check is a plain fetch and runs everywhere.

Next