Scrawn LogoScrawn Docs
Scrawn LogoScrawn Docs
Scrawn.js

Advanced Usage

Advanced patterns, optimization techniques, and best practices

Overview

This guide covers advanced usage patterns, optimization techniques, and best practices for production deployments with Scrawn.js.

Batch Processing

When tracking multiple events, use Promise.all for better performance:

import { Scrawn } from '@scrawn/core';

const scrawn = new Scrawn({
  apiKey: process.env.SCRAWN_KEY as `scrn_${string}`,
  baseURL: process.env.SCRAWN_BASE_URL || 'http://localhost:8069',
});

// Track multiple events in parallel
const events = [
  { userId: 'user-1', debitAmount: 100 },
  { userId: 'user-2', debitAmount: 200 },
  { userId: 'user-3', debitAmount: 150 },
];

await Promise.all(
  events.map(event => scrawn.sdkCallEventConsumer(event))
);

Async Event Tracking Pattern

In persistent servers, await after the response so that the response isn't dependent on the billing call.

app.ts
app.post('/api/generate', async (req, res) => {
  await scrawn.sdkCallEventConsumer({
    userId: req.user.id,
    debitAmount: 100,
  });
  // Start tracking (don't await yet)
  const trackingPromise = scrawn.sdkCallEventConsumer({
    userId: req.user.id,
    debitAmount: 100,
  });
  
  // Do your work
  const result = await generateContent(req.body.prompt);
  
  res.json({ result });
  
  // Wait for tracking to complete
  await trackingPromise;
});

Queue-Based Processing

For high-throughput scenarios, use a queue to decouple tracking from request handling:

import Queue from 'bull';

const usageQueue = new Queue('usage-tracking', {
  redis: process.env.REDIS_URL,
});

// Producer: Add to queue
app.post('/api/action', async (req, res) => {
  // Queue the event
  await usageQueue.add({
    userId: req.user.id,
    debitAmount: 10,
  });
  
  // Process request immediately
  const result = await doWork(req.body);
  res.json({ result, queued: true });
});

// Consumer: Process queue in background
usageQueue.process(async (job) => {
  const { userId, debitAmount } = job.data;
  await scrawn.sdkCallEventConsumer({ userId, debitAmount });
});

Graceful Error Handling

Allow your app to continue functioning even if tracking fails:

async function trackUsageGracefully(userId: string, debitAmount: number) {
  try {
    await scrawn.sdkCallEventConsumer({ userId, debitAmount });
  } catch (error) {
    // Log error but don't block request
    console.error('Failed to track usage:', error);
    
    // Optional: Queue for later retry
    await queueForRetry({ userId, debitAmount, error });
  }
}

Reuse SDK Instance

Always create the SDK instance once and reuse it:

lib/scrawn.ts
import { Scrawn } from '@scrawn/core';

export const scrawn = new Scrawn({
  apiKey: process.env.SCRAWN_KEY as `scrn_${string}`,
  baseURL: process.env.SCRAWN_BASE_URL || 'http://localhost:8069',
});
app/api/route.ts
import { scrawn } from '@/lib/scrawn';

// Use the shared instance
await scrawn.sdkCallEventConsumer({ userId: 'user-123', debitAmount: 10 });