Serverless and Flushing

Ensure traces are delivered in short-lived runtimes.

Serverless environments (Vercel, AWS Lambda, Cloudflare Workers) require special handling to ensure traces are delivered before the process exits.

The Problem

In serverless runtimes:

  1. The process may terminate immediately after returning a response.
  2. Background async tasks (like sending traces) may be killed.
  3. Buffered events are lost if not explicitly flushed.

The Solution: Explicit Flush

Always call flush() at the end of each request to best-effort deliver buffered events.

TypeScript

With Middleware (Recommended)

The SDK middleware handles flushing automatically:

  • Express/Fastify: Calls trace.flush() on response finish event.
  • Next.js: Calls trace.flush() before returning the response.

Without Middleware

export async function handler(req: Request) {
  try {
    const result = await processRequest(req);
    return result;
  } finally {
    // Critical: Flush before the function exits
    await njira.trace.flush();
  }
}

AWS Lambda

export const handler = async (event: APIGatewayEvent) => {
  try {
    const result = await processEvent(event);
    return { statusCode: 200, body: JSON.stringify(result) };
  } finally {
    await njira.trace.flush();
  }
};

Python

With Middleware (Recommended)

The FastAPI middleware automatically flushes after the response is produced.

Without Middleware

async def handler(request):
    try:
        result = await process_request(request)
        return result
    finally:
        await njira.flush()

AWS Lambda

def handler(event, context):
    try:
        result = process_event(event)
        return {"statusCode": 200, "body": json.dumps(result)}
    finally:
        # Note: sync flush for Lambda
        njira.flush_sync()

Configuration

Timeouts

Set a reasonable flush timeout to avoid hanging:

await njira.trace.flush({ timeoutMs: 2000 }); // Max 2 seconds
await njira.flush(timeout_ms=2000)

Buffer Size

Control how often the SDK auto-flushes during long-running processes:

Variable Description Default
NJIRA_BUFFER_SIZE Max events before auto-flush 100
NJIRA_FLUSH_INTERVAL_MS Auto-flush interval 5000

Best Practices

  1. Always use try/finally: Ensures flush runs even if the handler throws.
  2. Set reasonable timeouts: Don't let flush hang your response.
  3. Prefer middleware: Let the SDK handle flush timing automatically.
  4. Monitor for lost events: Check Console for gaps in trace data after deploys.

Edge Cases

Vercel Edge Functions

Edge functions have stricter execution limits. Use:

export const config = { runtime: 'edge' };

export default async function handler(req: Request) {
  // ... your logic
  await njira.trace.flush({ timeoutMs: 1000 });
  return new Response("OK");
}

Cloudflare Workers

Use waitUntil to extend the execution context:

export default {
  async fetch(request, env, ctx) {
    const result = await handleRequest(request);
    ctx.waitUntil(njira.trace.flush());
    return result;
  }
};