Architecture
Rendorix is a serverless, edge-first pipeline: clients only talk to HTTPS; originals never ship directly from a public bucket; transforms run only after policy and signature checks. The same logical path applies whether you use a custom domain or the CloudFront hostname your stack outputs.
The exact Terraform module names and whether validation runs in a CloudFront Function, Lambda@Edge, or another hook depend on the published infrastructure—treat the diagram as the reference model, not a binding bill of materials.
System diagram
Section titled “System diagram”At a high level, the delivery stack is a loop between the CDN, lightweight edge checks, and on-demand image work backed by private object storage.
flowchart TB
subgraph clients [Clients]
browser[BrowserOrBackend]
end
subgraph edge [Edge]
cdn[CloudFront]
signatureCheck[SignatureAndPolicy]
end
subgraph compute [Serverless compute]
imageFn[ImageTransformLambda]
end
subgraph data [Durable data]
originals[S3Originals]
presetCfg[PresetConfiguration]
secrets[SecretsForSigning]
end
browser -->|HTTPS| cdn
cdn -->|cacheHit| browser
cdn -->|cacheMiss| signatureCheck
signatureCheck -->|deny| deny403[ClientError403]
deny403 --> browser
signatureCheck -->|valid| imageFn
imageFn -->|getObject| originals
imageFn -->|resolvePresets| presetCfg
imageFn -->|imageBytes| cdn
browser -.->|build_signed_urls| secrets
Roles in short
| Component | Role |
|---|---|
| CloudFront | Global TLS, caching of successful image responses, and the public URL integrators use. |
| Signature and policy (edge) | Rejects unsigned, expired, or out-of-policy requests before heavy work (see Security). |
| Image transform (Lambda) | On a cache miss, loads the original from S3, applies presets / overrides, and returns bytes (e.g. via Sharp or equivalent). |
| S3 | Private source of truth for originals; not a public file browser for your app users. |
| Secrets | HMAC key material and similar values—stored in Secrets Manager, SSM Parameter Store, or your CI, never in the browser. |
Request path
Section titled “Request path”- The client issues
GETto your image URL (path + preset and signed query string, or your project’s equivalent). - CloudFront matches a cache key derived from the request (path + relevant query, vary rules, Accept if you negotiate formats—your policy should match the edge config).
- If there is a cache hit for a valid 200/304 response, CloudFront returns it—no Lambda runs.
- On a miss, the edge path evaluates signature, expiry, and allowlists (preset names, max dimensions, etc.). Fail fast with 4xx when something is off.
- The image Lambda (or the component your repo uses) GETs the original from S3 using least privilege IAM, decodes and transforms (CPU-bound work), then returns the bytes through CloudFront so the response can be cached according to your TTL and Cache-Control design (Caching, TTL).
- The client receives an optimized image; repeat visitors hit the CDN instead of re-running compute.
Keep cache keys stable: the same logical image (preset + source + options) should map to the same key so you get one transform per unique variant.
Origin and transforms
Section titled “Origin and transforms”- Origin (S3): Originals are stored as objects (e.g. JPEG, PNG, WebP in). Access is IAM-restricted; only the transform role and operational roles you define can
GetObject(and optionallyListfor admin tasks). - Presets: Named bundles (e.g. width, quality, output format) live in configuration the transform code reads—JSON in S3, environment for small static sets, or Parameter Store / DynamoDB if you need runtime updates. See Core concepts: Presets.
- Overrides: Optional per-request fields may narrow or adjust within bounds you define; document precedence in Usage: Overrides when you lock behavior.
- Transform runtime: Usually Node on Lambda with Sharp (or a similar library). Memory and timeout need to match your largest reasonable source images; giant uploads may require async or rejection policies.
The image worker is stateless between invocations: all state is S3 + config + secrets—which keeps scaling simple and Terraform-friendly.
Caching and edge
Section titled “Caching and edge”- CloudFront is the right place to amortize work: a miss pays compute + S3; a hit pays egress and request pricing, not a full Lambda run.
- TTL is split: signed URL lifetime (Signed URLs, Expiration) vs. HTTP cache for successful responses. Align them so you do not serve stale bytes past what your product allows, and so browsers do not fight the CDN.
- Invalidation is expensive as a day-one habit; prefer versioned or content-addressed keys if you need aggressive updates. For rare global changes, use CloudFront invalidation as an operational tool, not a per-edit workflow.
Configuration and state
Section titled “Configuration and state”| Kind of state | Typical home | Notes |
|---|---|---|
| Preset definitions | Repo JSON, S3 config object, or SSM | Ship with IaC when possible; version changes like app deploys. |
| HMAC / API secrets | Secrets Manager or SSM (encrypted) | Rotated on a schedule; Security. |
| Terraform state | S3 + DynamoDB lock (common pattern) | See Deployment: Terraform. |
| Per-request URL state | Query string (signed) | Exp, signature, preset—nothing secret in the browser-visible URL except what you intentionally expose. |
Nothing in the client should be able to mint valid signed URLs without your server (or build pipeline) and secret.
Failure modes and fallbacks
Section titled “Failure modes and fallbacks”| Failure | Likely effect | Mitigation (directional) |
|---|---|---|
| Invalid or expired signature | 403 at edge | Sync canonical signing with edge validation; HMAC. |
S3 throttling or NoSuchKey | 5xx or 404 from pipeline | Retry in Lambda with backoff; validate keys at upload time. |
| Lambda timeout or OOM | 5xx or partial response | Tune memory; cap max pixel count; reject pathological files early. |
| Cold start on first request after idle | Higher TTFB | Provisioned concurrency only if revenue-critical; else accept rare cold cost. |
| Stale CDN after deploy | Old images for TTL | Shorter TTL, key versioning, or invalidation (sparingly). |
| Signing key leak | Forged URLs until rotate | Rotate secret; short URL lifetimes; audit who can sign. |
For multi-region or zero-downtime deploys, your IaC and CloudFront behavior need their own runbook—start from Deployment: AWS setup.
Related reading
Section titled “Related reading”- Quick start — end-to-end deploy and first signed URL
- Core concepts — presets, caching, TTL
- Tradeoffs — cost vs complexity vs caching behavior