Skip to content

devlog/api-plumbing/webhooks-polling-streaming-cut-your-ai-app-bill-483.md

Webhooks, Polling, Streaming: Cut Your AI App Bill

Your terminal spinner is not the expensive part

You kick off a model request, watch a spinner, and eventually get text. Behind that simple interaction are two separate decisions: how generation runs, and how your app receives its output. Confusing them is an easy way to pay twice.

Webhooks, polling, and streaming mostly change delivery costs: open connections, status requests, worker time, and operational complexity. They do not inherently reduce model tokens. The real savings come from avoiding duplicate generations, stopping unwanted work, and choosing infrastructure that matches the job.

Separate generation from output delivery

Start with one durable job record containing an application-generated ID, request fingerprint, state, and eventual result location. Submit generation once, then let clients observe that job. Reloading a browser or reconnecting a terminal should not automatically launch another paid request.

Fluxo gives you one key and one base URL, https://api.fluxorelay.com, across its model catalog. You might use DeepSeek V4 Flash for routine extraction and Claude Sonnet 5.5 for a harder review. Delivery mechanics still need checking per endpoint; a shared API entry point does not imply universal background-job or webhook support.

Stream interactive answers without buffering the whole response

Streaming fits chat, editor assistants, and terminal tools because users see progress before generation finishes. Forward chunks as they arrive instead of collecting everything in your backend first. Check proxy buffering, connection timeouts, and disconnect handling before calling the feature shipped.

The savings opportunity is cancellation. If someone closes a panel or presses Ctrl-C, propagate cancellation upstream where supported. Closing your frontend connection alone may leave generation running. Cancellation is best effort: already processed tokens remain billable, and the upstream request may finish before cancellation takes effect.

Fluxo works with Claude Code, Codex, Gemini CLI, and any OpenAI SDK. Keep application-level cancellation and retry behavior explicit rather than assuming your tool's defaults minimize spend.

Poll your job record, not the generation endpoint

Polling is often the cheapest implementation for occasional background work. Return a job ID immediately, run generation in a worker, and expose a small status endpoint backed by your own database. Polling should read state, never recreate the original model request.

  • Start with a short delay, then increase intervals with jitter.
  • Stop polling when jobs finish, fail, or exceed their deadline.
  • Return compact status responses instead of repeating the full output.
  • Let reconnecting clients resume observation using the existing job identifier.

Estimate the overhead before optimizing it. A thirty-second job polled every two seconds produces roughly fifteen status reads. At low volume, that can be simpler and cheaper than operating webhook delivery. At scale, those reads and HTTP requests deserve their own budget.

Use webhooks for durable background completion

Webhooks suit document processing, batch enrichment, and workflows where nobody needs a live cursor. If the selected API supports completion callbacks, use them. Otherwise, your worker can persist the result and send your application's own webhook. Do not invent a relay webhook endpoint based on an SDK example.

Persist incoming events before acknowledging them, verify signatures when available, and process duplicate deliveries idempotently. Retry failed webhook delivery without rerunning generation. Keep large outputs in storage and send an authenticated result reference rather than repeatedly shipping megabytes.

Measure token spend separately from transport overhead

Fluxo bills per real token, including cache reads and writes, with no monthly fee. Track those categories separately from queue operations, database reads, webhook retries, and connection duration. A cache hit is not automatically free, and a shorter wait is not automatically a smaller model bill.

Record generation attempts per job and flag anything above one. For ambiguous upstream timeouts, reconcile request status where possible before retrying; your local idempotency key cannot guarantee upstream deduplication. Fixing one accidental double submission can beat weeks of tuning polling intervals.

Choose delivery by the waiting experience

Stream when a person is watching. Poll when background volume is modest and simplicity wins. Use webhooks when durable completion events justify the machinery. If you want to test that split, you can create a Fluxo account and measure one representative workflow.

Keep incentives separate from benchmarks: Fluxo users earn a referral share when people they invite pay, but your delivery choice should follow measured costs and failure behavior.

Next in the buffer

Sign up in a minute and get credit to try every model mentioned here. Sign up →