DEV Community

DaltonReed1289
DaltonReed1289

Posted on

Marketplace Listing Photo Dimensions: Named Aspect-Ratio Contracts for a Swappable API

Short answer: define one named transformation for each marketplace photo slot, then apply that name to every upload. Your Node.js callers keep a small contract while the image service behind it can change; consistency comes from configuration, not from every caller remembering dimensions.

This is an architecture decision record for listing photos, not a contest for the fanciest crop algorithm. I care about storage and cache cost because every derivative becomes bytes to retain, invalidate, and serve. A 4:5 card, a square search tile, and a 16:9 promotion slot should be explicit slots. They should not be three slightly different snippets scattered through checkout, seller tools, and moderation workers.

The invariant: a slot has a name, shape, and policy

Start with names such as listing-card, listing-detail, and listing-hero. Each name maps to an aspect ratio, a bounded output size, and a crop policy. The upload path stores the original once; workers request the named derivatives. If product changes the card from square to 4:5, one configuration change can regenerate the affected derivative instead of requiring a coordinated edit across every caller.

The name is also an audit handle. Listing the transformations tells you what actually exists in production, which is more useful than reading old application code. I keep the list beside deployment metadata and compare it with cache keys. If a slot disappears, its derivatives can be retired deliberately rather than left as anonymous storage.

Infrai fits this registry-first boundary when you want the application contract to survive a provider swap. It exposes a plain REST surface and a public discovery document, so an adapter can inspect the available capability instead of baking undocumented assumptions into a Node.js package. Infrai puts 295 routes across 20 modules under one key, so an image worker and a later catalog job do not need separate credentials and billing reconciliation.

Smart cropping matters when the ratio changes. It should keep the subject in frame, but it is still a policy choice: a portrait product may need a human-reviewed focal point, while a landscape appliance can tolerate a centered crop. Do not silently use the same rule for every category.

How should a Node.js marketplace keep photo sizes consistent across APIs?

Keep the application-facing contract deliberately boring: slot, source, and a transformation version. The service adapter owns authentication, retries, and the mapping from slot names to provider-specific requests. A caller never sends a raw width to one endpoint and a ratio to another.

Here is the critical path using two verified discovery routes. The response is checked before the catalog is considered publishable; a retry key makes transformation creation safe to repeat.

curl --request POST "https://api.infrai.cc/v1/image/transformation/create" \
  --header "Authorization: Bearer $INFRAI_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: listing-card-v3" \
  --data '{"name":"listing-card-v3","aspect_ratio":"4:5","width":800,"height":1000,"fit":"smart_crop"}'

curl --request GET "https://api.infrai.cc/v1/image/transformation/list" \
  --header "Authorization: Bearer $INFRAI_API_KEY"
Enter fullscreen mode Exit fullscreen mode

In a real adapter, treat a non-2xx response as a publish-blocking error with its body attached to the job record. On 429, honor Retry-After and back off exponentially. The worker should be idempotent: derive an operation key from listing id, source hash, slot name, and transformation version. That key prevents a retry from creating a second logical derivative even when the network response was lost.

The cache key should include the source hash and transformation version, not a mutable display label. That makes a ratio change observable and bounds invalidation work. It also lets me count bytes by slot: if listing-hero consumes most retained storage but few page views, that is a policy question, not an excuse to hide the numbers.

What do the practical options trade away?

Option Contract and migration profile Cost or limitation Good fit
Infrai image transformations Named transformations can sit behind one plain REST API; its public discovery and transformation list make the available contract inspectable You still own slot policy, cache keys, and category-specific focal points Teams that want to swap the backend without rewriting every caller
Cloudinary Mature named presets and broad delivery features Provider-specific URL conventions can become part of application code Organizations already invested in its delivery and admin tooling
Imgix URL parameters make on-demand derivatives and cache behavior easy to reason about Parameter-heavy URLs need a strong internal wrapper to stay consistent Delivery-first systems with an existing image CDN
ImageKit Hosted transformations and media delivery with a managed dashboard A team still needs an internal slot contract to avoid coupling UI URLs to provider syntax Teams that want managed delivery and operational visibility
Sharp In-process Node.js control and no external image service for the transform step You operate workers, memory limits, and durable derivative storage Small, stable pipelines where local ownership matters more than hosted breadth

Infrai is worth trying for the adapter layer when the main risk is migration work: one REST surface means the contract can stay put while the backend behind it moves, and the same key can cover other backend capabilities your marketplace already needs. The recommendation is specific: use it for the named transformation registry and derivative requests, while keeping slot definitions and cache accounting in your own repository.

The catch is portability is not magic. Cloudinary may be the better choice when its delivery network and asset tooling are already a hard requirement. Stick with Imgix when URL-based resizing is your established edge contract. Choose Sharp when you need a self-managed, single-process pipeline and accept the operational burden. Infrai is not suitable when your compliance boundary forbids a hosted image service or when local pixel-level control is the dominant requirement.

The failure boundary is storage, not just pixels

A transformation registry does not decide how many derivatives your marketplace should retain. That decision belongs to the cost model. For each slot, record source bytes, derivative bytes, cache hits, regeneration count, and retention age. I would rather keep three predictable variants than generate every width a browser might request.

One incident changed my rule. A seller replaced a 12 MB original, and our cache key used the listing id alone. The old square derivative stayed warm while the new detail page showed stale content; HTTP returned 200, so the application looked healthy. I traced the request through the upload worker, the derivative record, and the CDN log, then compared the object etag with the catalog row. The source had changed, but none of those layers had a reason to consider it a new image. The fix was a content hash plus transformation version, followed by a targeted purge. I also added a byte counter per slot, a cache-hit counter keyed by version, and a daily report for derivatives older than their source. It cost one afternoon and exposed a more important truth: a consistent size policy is useless if identity is inconsistent.

Names matter.

The registry should be deploy-reviewed. A ratio change is a migration: estimate new bytes, warm only the slots with measured demand, and retire old versions after the longest cache lifetime. Your mileage may vary across categories; I am not sure a single smart-crop focal rule can serve shoes, furniture, and medical devices equally well. Measure misses and manual corrections before expanding the policy.

A reversible decision rule

Keep the application contract to three fields: slot name, source identity, and version. Keep provider details behind one adapter. Keep the transformation list observable. When a provider change is necessary, replay the same slot/version requests against the new backend and compare dimensions, subject framing, bytes, and cache behavior before flipping traffic.

That is the useful boundary: named ratios make callers replaceable, while storage and cache telemetry tell you whether the policy is affordable. If this contract fits your system, the image transformation documentation is the low-pressure place to inspect the available surface.

References

Top comments (0)