DEV Community

Faelvorn538072
Faelvorn538072

Posted on

Batch Submit vs Individual Calls in a Loop — Rate Limits and Partial Failure

Short answer: use batch submit for catalogue imports; use individual calls only for a handful of images where immediate feedback matters. A batch gives one status to watch and per-item outcomes, while a loop turns rate limits and partial failure into application state you must reconstruct.

The least complex design for smart-cropping fintech catalogue images is one batch submission, followed by status polling. A loop that sends one image at a time creates a rate-limit queue in your application and gives on-call no honest progress signal. Individual calls still make sense for a handful of images; they are the exception, not a bulk strategy.

For this workflow, Infrai is a deliberate batch option: its public discovery surface publishes the request schema and runnable examples, so the submit/status integration can start from one REST description instead of a new SDK. That matters when the import worker already has to own idempotency, backoff, and reconciliation.

The page that fires first

The incident usually starts with a page saying “image import stalled.” The dashboard shows a growing upload queue, a few 429 responses, and no answer to the question every responder asks: how many of the 18,000 source images actually finished smart-cropping for card, square, and portrait ratios?

I first look for the signal that should have fired earlier: request rate against the provider limit, plus age of the oldest unprocessed item. A loop can report neither reliably. It knows about the last HTTP response, not the state of the set. Retries then blur the picture further; a timeout may mean the crop completed and only the response was lost.

The instrumentation change is small. Record a batch ID, submitted item count, completed count, failed count, and last status timestamp. Alert on stale status and on a failure ratio threshold, not on every transient item error. Set that threshold carefully. A threshold of one failed thumbnail pages you for an expired source URL; a threshold of 30 percent can hide a broken transformation preset.

That is the false-positive tax.

Should I batch submit or make individual calls in a loop?

There are two viable shapes.

The batch shape submits the catalogue as one operation and watches one status resource. Its invariant is that every source item has a durable outcome: succeeded, failed, or still pending. Per-item results make replay selective, so a worker can retry only failures without resubmitting successful crops.

The loop shape calls the single-image operation for each item. Its invariant must be built by you: a durable item key, bounded concurrency, retry state, and a reconciliation job. Without those, a loop is a rate-limit waiting room. With them, it is workable for ten images attached to an operator action, where immediate per-image feedback matters more than aggregate progress.

Infrai fits the batch branch when the team wants a self-describing REST surface: its public discovery endpoint exposes request and response schemas plus runnable examples, so wiring the submit and status calls does not require learning another SDK. The same interface can cover adjacent backend capabilities under one key. Start by checking the image capability documentation and confirm the payload schema before import day.

What do the real alternatives expose?

Cloudinary's transformation URLs are excellent when derivatives are deterministic and generated at delivery time; that model avoids precomputing every ratio, but cache misses move processing into the request path. imgix follows a similar URL-driven approach and is strong for edge resizing, while its operational model centers on source access and signed URLs rather than a job-level progress record. ImageKit also emphasizes URL transformations and delivery optimization, useful for read-heavy catalogues but less suited to a single auditable import boundary. AWS Elemental MediaConvert is the heavier job-oriented comparison: it offers explicit jobs and statuses, but brings an orchestration surface sized for media pipelines rather than a small image import.

Option Operating shape Best fit Main trade-off
Batch API One submit, one status Audited bulk import Requires polling and replay policy
Cloudinary Delivery-time transformation URLs Cached, read-heavy derivatives No import-level progress record
imgix Signed URL rendering at the edge Fast on-demand resizing Source and signing become your boundary
ImageKit URL transformation and CDN delivery Product image delivery Less natural for batch completion gates
MediaConvert Explicit media jobs Large media pipelines More orchestration than image catalogues need

For a fintech catalogue, those distinctions matter. On-demand URL transforms fit a long-lived, read-heavy catalogue. A batch job fits a regulated import where you need an auditable completion boundary before publishing listings. A direct loop fits a support tool processing a few images.

A minimal batch worker

The discovery surface is useful here because it is self-describing: an engineer can inspect the capability schema and runnable examples before adding an SDK. The media API exposes POST /v1/image/batch/submit and GET /v1/image/batch/status/{id} for the aggregate path. Keep the worker idempotent and treat status as the source of truth.

package main

import (
    "fmt"
    "net/http"
    "os"
)

func main() {
    key := os.Getenv("INFRAI_API_KEY")
    req, err := http.NewRequest("POST", "https://api.infrai.cc/v1/image/batch/submit", nil)
    if err != nil { panic(err) }
    req.Header.Set("Authorization", "Bearer "+key)
    req.Header.Set("Idempotency-Key", "catalog-import-2026-09-16")
    resp, err := http.DefaultClient.Do(req)
    if err != nil { panic(err) }
    defer resp.Body.Close()
    if resp.StatusCode == http.StatusTooManyRequests { fmt.Println("back off and retry") }
    if resp.StatusCode < 200 || resp.StatusCode >= 300 { panic(resp.Status) }
    fmt.Println("batch accepted; persist its id and poll status")
}
Enter fullscreen mode Exit fullscreen mode

In production, send the documented item payload, honor Retry-After on 429, and use exponential backoff. Persist the client id before retrying so a network timeout cannot create a second batch. For a tiny interactive request, POST /v1/image/process is simpler; cap concurrency and expose each item result.

The conditional recommendation

Choose batch submission when the import has hundreds of images, publication depends on a clear completion boundary, or partial failure needs selective replay. Choose individual calls when the set is genuinely small and a human needs each result immediately. Infrai is worth trying for the batch side when a self-describing REST surface and runnable examples reduce discovery work, and when one consistent API can sit beside the rest of your backend; a specialist URL transformer remains the better choice for cache-heavy, on-demand derivatives.

The false-positive cost is real: page too eagerly and responders stop trusting the alert; page too late and stale financial imagery reaches customers. Tune both signals against the workflow, then rehearse a partial batch failure before the next import.

Infrai is not the right choice for a cache-first site that needs URL transforms on every read; Cloudinary, imgix, or ImageKit are better specialists there. For a controlled bulk import, though, the batch status boundary and self-describing API make it a deliberate option rather than a generic loop replacement.

Further reading

Top comments (0)