case studies

Treating an uploaded image as an input to verify

A first-party image-ingestion implementation using staged object storage, signed upload claims and immutable optimized output.

Context

Editors need to attach media without putting large binary files in the application database. The public website also needs predictable image dimensions and useful descriptions.

The constraint

An extension or browser-supplied MIME type does not establish that an upload contains a valid image. Retrying completion should not replace an already published object.

The approach

The API signs a bounded staging upload and a completion claim. Completion verifies the stored object size and type, bounds streamed bytes, decodes the image, rejects unsupported or animated inputs, strips metadata and emits a separate WebP asset.

Architecture

Image ingestion boundary
  1. 01Editor selects an image
  2. 02Signed upload to a private staging key
  3. 03API verifies object and decodes pixels
  4. 04Immutable WebP asset and metadata
  5. 05Responsive public rendering

Decisions and tradeoffs

Original staging objects remain private. Only the optimized asset path is intended for the public asset origin.

Metadata removal is soft deletion. Reference checks protect used assets, while physical retention and cleanup remain an explicit operations task.

Implementation

Supported inputs are PNG, JPEG, WebP and AVIF. The decoder caps input pixels and limits output dimensions; the object is stored under a distinct immutable key.

Inspect the media implementation

Evidence and outcomes

A local integration test performs a real signed POST against an S3-compatible emulator, completes the upload and verifies decoded WebP output. Production bucket policy and CORS require deployment configuration.

Discuss an API integration

Stack

NestJS

PostgreSQL

Prisma

Next.js

A clear next step

Bring us the constraint.

Share the product, the problem and what a useful outcome looks like. We’ll discuss the scope before committing to delivery.

Discuss your project
Start a project