Overview / Platform / media
ADR 0036
Media is stored in S3 behind cdn.inkress.com, uploaded via the API with content-addressed dedup
AcceptedPlatform / media
Context
Merchants and the platform upload images and files — product images, logos, KYC documents. These need durable storage, fast global delivery, and de-duplication so the same file isn't stored many times. The main design fork is whether clients upload directly to object storage (presigned URLs) or through the API (server-side proxy).
Decision
Store uploaded media in AWS S3 (bucket commercian), serve it from cdn.inkress.com (a CDN pull-zone in front of the bucket), and upload through the API with content-addressed de-duplication.
- Proxied upload. Binaries are sent to the API, which stores them in S3 — not presigned direct-to-S3 — so the API can validate and authorize the upload in-band.
- Content-addressed within a prefix. A file's MD5 hash is appended to its (slugified) name inside a per-uploader path prefix (
/{prefix}/{name}_{md5}{ext}), and an existence check skips re-uploading a file already at that path — so a repeated identical file from the same uploader is stored once. Dedup is per-prefix, not global across all merchants. - CDN delivery. Objects are served from
cdn.inkress.com, decoupling the public URL from the bucket host. A public, unauthenticated/v1/files/publoadendpoint exists for public uploads.
Consequences
- Positive: durable object storage plus CDN delivery, with single-copy storage of a repeated identical file from the same uploader (per-prefix); the API mediates every upload (validation/authorization) rather than exposing S3 directly.
- Neutral / to revisit: proxying binaries through the API consumes app bandwidth and memory that a presigned direct upload would offload to S3 — an acceptable trade for in-band control at current volumes, revisitable if large-file uploads grow.
- Neutral / to revisit: the public
publoadendpoint is an abuse/cost surface to keep an eye on; sensitive documents (KYC) live in the same store and rely on app-layer access control.
Alternatives considered
- Presigned direct-to-S3 upload: not adopted — it removes the API's chance to validate/dedup in band; the proxy path was chosen despite its bandwidth cost.
- Bunny CDN (or another CDN) as the primary store: not adopted for media — S3 +
cdn.inkress.comis the media store; Bunny is used only for short links. Earlier S3+CloudFront/imgix setups were migrated away from. - Path by opaque id instead of content hash: rejected — content addressing gives dedup for free; an opaque id would store duplicates of the same bytes.