Skip to content
ub3r.io

API Integrations Masterclass · Chapter 4 · 13 min

Pagination, batching and throughput

Cursor pagination, bulk endpoints and staying under rate limits at scale.

Cursors beat offsets

Offset pagination asks the database to skip thousands of rows on every request which is inefficient. Message logs are append-heavy, so offsets are exactly the wrong tool for the job. Cursor pagination encodes the position of the last item you saw into an opaque string for the next call. This approach remains performant even when you are millions of messages deep into your logs.

js
let cursor = null;
do {
  const page = await api.messages.list({ limit: 100, after: cursor });
  for (const m of page.data) await archive(m);
  cursor = page.has_more ? page.next_cursor : null;
} while (cursor);

Batching for Efficiency

Bulk endpoints accept many messages in one request and return per-item results to reduce overhead. Treat the response as a list of independent outcomes because some items will fail while others succeed. Give each item its own idempotency key so partial retries are safe for the entire batch. This is far more efficient than sending a thousand individual POST requests over high-latency connections.

Throughput and rate limits

Rate limits are usually expressed as a token bucket with a refill rate and a burst size. The right client strategy is a local limiter that matches the provider's published rate limits. Without the local limiter you will oscillate between bursting and getting throttled by the server. This oscillation is bad for your application's throughput and can put unnecessary strain on internal systems.

Handling the token bucket

Implementing a local token bucket or leaky bucket algorithm helps smooth out your outgoing traffic. This ensures that you are utilizing your full allocated bandwidth without constantly hitting the ub3r platform's limits. It also makes your application's performance more predictable, which is essential for meeting Service Level Agreements. Consider using a centralized rate-limiting service if you are running multiple instances of your application.

Scaling your Infrastructure

As your messaging volume grows, you will need to scale your worker pool to handle the load. Use horizontal scaling to add more workers that can process messages from your internal queues in parallel. Ensure that each worker respects the global rate limits to avoid being blocked by the ub3r API. A distributed architecture is the best way to handle millions of messages daily with high reliability.

Discussion (4)

ML
Marcus Lindqvist · 2026-10-08

Would love a follow-up on how this behaves under carrier throttling. We see very different numbers per route.

LF
Lena Fischer · 2026-10-12

Same experience here. Per-route metrics were the only way we found it.

PR
Priya Raman · 2026-10-09

Ran the playground with three concurrent sends — receipts came back out of order, exactly as the text says. Great way to make it stick.

TH
Tomás Herrera · 2026-10-01

We learnt the idempotency lesson the expensive way: duplicate OTPs during an incident. This chapter is now required reading on my team.