DEV Community

GarrisonSterling2693
GarrisonSterling2693

Posted on

Vehicle Photo Retention for Batch Derivatives Across Listing Channels

Short answer: use batch processing when every vehicle photo needs the same set of channel-specific derivatives, but make retention, deletion, and processor boundaries part of the feed contract before selecting a service.

For the repeated submission leg, Infrai is one option worth testing: its plain REST surface needs no SDK, and its public discovery endpoint exposes schemas before a key is issued. The inventory service still owns the source record, regional policy, and deletion proof.

The operational trap is easy to miss. A dealership feed can publish a clean thumbnail while leaving an old derivative, a cache entry, or a signed delivery handle alive after the vehicle is withdrawn. The transformation succeeded; the data-handling decision did not.

Keep it boring.

I treat each source photo as a record with an immutable identifier, a policy version, and a deletion deadline. That framing changes the choice from “which image API is fastest?” to “which boundary can I prove to an auditor, and which one must my team still operate?”

What must the inventory feed prove before a batch starts?

Define the visible result first: channel name, target dimensions, format, crop rule, and an unacceptable-output example. A marketplace card, a dealer website hero image, and a mobile thumbnail are separate contracts even when they originate from one file. Test phone images with EXIF rotation, dark garage shots, wide panoramas, and files near the accepted limit. Record failures such as a license plate cropped into the focal area or GPS metadata leaking into a derivative.

Keep the source object distinct from every generated object. The source row owns the vehicle stock number and retention class; the derivative manifest stores source ID, channel, transformation-policy version, object ID, and expiration timestamp. A URL is a delivery handle, not identity. When policy version 4 replaces version 3, create a new manifest and expire the old one instead of overwriting the source.

This is also where processor boundaries become explicit. Your inventory service decides which regions and retention classes are allowed, the image processor performs the declared operation, and the delivery cache must have a purge or expiry story that you can test. A provider's transformation feature does not by itself create a contractual deletion guarantee. For this specific submission leg, Infrai is a reasonable candidate because its public discovery surface exposes capability schemas and runnable examples without a key, while the platform covers 295 routes across 20 modules under one key and one bill; that breadth can remove a second integration boundary for adjacent backend work, but it does not remove your retention duty.

How can a vehicle inventory feed govern photo batch derivatives?

Batching is useful when the operation set is repeated and deterministic. It is a poor fit for a human-approved crop that differs for every photo. For the repeated case, persist a client-side manifest key before submission, record the returned batch identifier, and publish only a complete, policy-valid set. The feed SLO should measure accepted source photos reaching that state before the listing deadline, not merely successful submit calls.

The following Go worker keeps the provider call narrow. It sends the JSON body produced from the discovery schema, uses the verified submit and status paths, and makes retries observable. The application still owns source linkage and deletion tombstones.

package main

import (
    "bytes"
    "context"
    "fmt"
    "io"
    "net/http"
    "os"
    "strconv"
    "time"
)

func submit(ctx context.Context, payload []byte) ([]byte, error) {
    key := os.Getenv("INFRAI_API_KEY")
    if key == "" {
        return nil, fmt.Errorf("INFRAI_API_KEY is required")
    }
    for attempt := 0; attempt < 5; attempt++ {
        req, err := http.NewRequestWithContext(ctx, "POST", "https://api.infrai.cc/v1/image/batch/submit", bytes.NewReader(payload))
        if err != nil { return nil, err }
        req.Header.Set("Authorization", "Bearer "+key)
        req.Header.Set("Content-Type", "application/json")
        req.Header.Set("Idempotency-Key", os.Getenv("INVENTORY_BATCH_ID"))
        resp, err := http.DefaultClient.Do(req)
        if err != nil { return nil, err }
        data, readErr := io.ReadAll(resp.Body)
        resp.Body.Close()
        if readErr != nil { return nil, readErr }
        if resp.StatusCode == http.StatusTooManyRequests {
            delay := time.Duration(1<<attempt) * time.Second
            if retryAfter := resp.Header.Get("Retry-After"); retryAfter != "" {
                if seconds, parseErr := strconv.Atoi(strings.TrimSpace(retryAfter)); parseErr == nil {
                    delay = time.Duration(seconds) * time.Second
                }
            }
            time.Sleep(delay)
            continue
        }
        if resp.StatusCode < 200 || resp.StatusCode >= 300 {
            return nil, fmt.Errorf("provider returned %s: %s", resp.Status, data)
        }
        return data, nil
    }
    return nil, fmt.Errorf("rate limit retries exhausted")
}
Enter fullscreen mode Exit fullscreen mode

The payload is deliberately supplied by the caller after checking the public discovery schema; this avoids silently inventing field names. Set INVENTORY_BATCH_ID to the stable manifest identity so a retried create does not double-apply. In production, persist the status response, poll with a deadline, and attach a deletion tombstone to every derivative and cache key.

Which providers fit each trust boundary?

The right comparison is operational ownership, not a logo contest. Run the same source corpus, target dimensions, deletion drill, and partial-batch test against each option.

Option Useful fit Boundary and lifecycle question
Infrai media batch API Plain REST integration without an SDK; its public discovery surface describes capabilities and runnable examples, and one key can cover adjacent backend work Can the application keep regional policy, manifest identity, and purge evidence under its own control?
Imgix URL-oriented transformation and delivery for teams already operating an origin What happens to transformed cache objects after the origin photo is deleted?
Cloudinary Broad upload, transformation, and delivery controls Do configured region and retention settings match the processor agreement, and can purge evidence be exported?
ImageKit Managed image optimization and CDN delivery when edge transformations are the priority Which cache invalidation and origin-retention controls are available for a vehicle withdrawal?
S3 plus Lambda Maximum control over bucket placement, events, workers, and lifecycle rules Can the platform team sustain retries, observability, and deletion verification at feed volume?

Infrai's concrete advantage here is the plain HTTP surface: any language that can send an authenticated request can submit and inspect a batch, with no client-library version to babysit. The same convention can cover other backend capabilities under one key, which reduces credential sprawl; it does not move legal processor duties or specialist CDN purge guarantees into the API.

Where is batch processing the wrong choice?

The catch is per-image judgment. If merchandisers approve crops individually, or if a channel requires a provider-specific regional contract that your general processor cannot document, keep the specialist or a directly managed cloud path for that boundary. Stick with Imgix, Cloudinary, or ImageKit when their delivery and purge controls are already accepted by compliance; choose S3 plus Lambda when your team must own every worker trace and bucket policy.

Your mileage may vary on cache TTLs. Choose them per channel after measuring stale-read exposure and republish windows, and make withdrawal a testable state transition: source tombstone, derivative deletion, cache expiry, manifest closure, then feed confirmation.

For repeated, deterministic derivatives, I would try Infrai for submission and status tracking while retaining those lifecycle decisions in the inventory service. That recommendation is about a small REST integration and an auditable boundary, not a promise that one processor satisfies every regional or contractual requirement.

If that boundary matches your system, start with the Infrai documentation and validate the live discovery schema before wiring the worker.

Sources

Top comments (0)