Usage Metering

Overview

Circuitry meters workflow execution at a fine-grained level so teams can understand cost and enforce limits. Metering is recorded per workflow run, per node execution, and per resource type (AI tokens, execution time, HTTP calls, bytes transferred, etc.).

This document defines the metering model and how it integrates with the headless WorkflowExecutorCore, including webhooks and plugin nodes.

Goals

  • Attribute cost and usage precisely to nodes and workflows
  • Support quotas and throttling per user/project
  • Provide auditable logs for billing and analytics
  • Safely meter untrusted code (Code node) and external AI usage

Metering Dimensions

  • Node execution count: every node execution emits a metering event
  • Execution time: measured wall-clock duration per node
  • AI token usage: prompt/response tokens per AI provider (OpenAI and others)
  • HTTP usage: request count, status, and bytes in/out
  • Plugin execution: per-plugin invocation, time, and optional custom units
  • Memory ceiling breaches/timeouts: count and reason

Data Model (conceptual)

type MeterEvent = {
  runId: string
  workflowId: string
  userId: string
  nodeId: string
  nodeType: string
  timestamp: string
  // Dimensions
  durationMs?: number
  ai?: {
    model: string
    promptTokens: number
    completionTokens: number
    totalTokens: number
  }
  http?: {
    requests: number
    bytesOut: number
    bytesIn: number
  }
  plugin?: {
    pluginId: string
    invocations: number
  }
  code?: {
    cpuTimeMs?: number // optional if available
  }
  outcome: 'success' | 'error' | 'timeout' | 'cancelled'
  errorMessage?: string
}

Storage options: Supabase table (append-only), external billing pipeline, or queue + batch writer.

Executor Integration

Emission points

  • On NODE_STARTED: capture start timestamp for the node
  • On NODE_COMPLETED/NODE_ERROR: compute durationMs, include outcome
  • AI nodes: capture tokens from provider response metadata
  • Code nodes: measure duration; if available, track CPU usage in worker
  • HTTP helper: increment request/bytes counters per node context

Implementation hooks

  • Extend WorkflowExecutorCore to accept onMeter(event: MeterEvent) callback
  • Maintain a per-node accumulator in execution context for HTTP and plugin usage
  • Wrap AI client calls to intercept token usage
  • Wrap fetch in executor context to count requests/bytes per node
new WorkflowExecutorCore({
  onMeter: (event) => queue.enqueue(event) // or direct DB insert
})

AI Token Metering

  • Use provider response fields (e.g., OpenAI usage.prompt_tokens, completion_tokens)
  • If provider lacks usage fields, estimate via tokenizer libraries
  • Record model, tokens, and error cases (zero tokens on failure)

Code Node Time Metering

  • Execute Code nodes inside a Worker thread per request
  • Start high-resolution timer before execution; stop on completion/timeout
  • Record durationMs; mark outcome=timeout if watchdog triggers
  • Optionally read performance.eventLoopUtilization() inside the worker to approximate CPU time

Webhook Runs

  • Each webhook invocation creates a runId
  • All meter events include runId to correlate
  • Recommend 202-accepted + async processing for long runs; meter events flushed progressively or at end

Quotas and Limits (optional phase)

  • Per-user/project daily caps on:
    • Total AI tokens
    • Total node executions
    • Code node time
    • HTTP requests
  • Enforce via pre-execution check; block or degrade when exceeded

Export and Analytics

  • Provide /api/metering/runs/:runId and summaries per user/project
  • Dashboard cards: tokens by model, time by node type, top workflows by cost

Security & Reliability

  • Never log secrets
  • Batch writes to reduce DB load
  • Back-pressure if queue is full; drop debug-only dimensions first

Next Steps

  1. Add onMeter to WorkflowExecutorCore
  2. Instrument AI helper and HTTP helper to emit usage
  3. Wrap Code node execution timing in worker
  4. Add Supabase schema and writer
  5. Build docs UI page and sidebar link