cdn assets.md
Deliver public assets through CDN for Express
Summary
Deliver public assets for a Express app through the Ample CDN. Publish a bucket with ample bucket publish, upload versioned assets with long-lived Cache-Control headers, and reference the CDN URL (https://cdn.
Infrastructure requirements
- Compute: verified (Apps run in isolated x86_64 Firecracker microVMs that auto-pause when idle and wake on request; sizes are the priced VM sizes.)
- CDN: verified (The CDN host serves objects from published buckets. It does not front app compute and is not a cache or key-value store.)
Prerequisites
- A bucket created with
ample bucket createand published withample bucket publish(its public URL is the CDN base) - An S3 client in the app to upload assets under versioned keys
- An Ample account token with servers:write and buckets:write
Exact tested configuration
- template:
node-22 - runtime:
node - size:
s-1vcpu-1gb - install:
npm install - build:
npm run build --if-present - start:
npm run start
Steps
Publish the bucket. Publishing makes objects readable at the CDN URL; keep private data in a separate, unpublished bucket.
ample bucket publish <bucket-name>Upload versioned assets. Use keys such as assets/
/file and set Cache-Control: public, max-age=31536000, immutable; change the version to invalidate. Reference the CDN URL. Pass S3_PUBLIC_URL to the app and build asset URLs from it.
ample deploy . --name <app-name> --public --env S3_PUBLIC_URL=... --env S3_ENDPOINT=... --env S3_REGION=... --env S3_BUCKET=... --env S3_ACCESS_KEY_ID=... --env S3_SECRET_ACCESS_KEY=...Verify delivery. Fetch /asset-url for the asset URL, then fetch that URL: the CDN must return the asset.
Verify. Fetch the live URL and run the success checks below. On failure read the build log, then the runtime log, fix the cause and deploy again; do not blind-retry.
ample logs <deployment_id> --kind build
Tested examples
- Express CDN assets canary (tests/deploy-canaries/express-cdn-assets): Versioned asset uploaded to a published bucket and served from the CDN URL.
Success checks
- asset URL resolves through the CDN (
/asset-urlon the live URL, expect https://cdn.)
Limitations
- Verified on the node-22 template at s-1vcpu-1gb; other templates and sizes are not verified by this recipe.
- Region, compliance attestations and request-duration limits are unknown and not claimed.
- Apps auto-pause when idle and wake on the next request; always-on is an operator setting, not a plan feature.
- PutObject and GetObject with path-style addressing are verified; multipart upload, listing, presigned URLs and lifecycle rules are not verified.
- Bucket credentials are passed as encrypted environment variables; the catalog never creates the bucket for you (use
ample bucket create). - Storage is allocation-priced per bucket quota and capped by the account plan; the estimate below covers compute only.
- The CDN serves objects from a published bucket only; it does not front the app's own responses.
- Cache rules, purge and TTL control are not verified; the fixture sets Cache-Control on upload and versions asset keys instead.
Cost estimate
Estimated 5.00 USD per month (size prices from pricing.toml at build revision a1b8c38919e59cd035ebabaced73cf84ece24371).
- app server x1
s-1vcpu-1gb: 5.00 USD
Verification evidence
- canary_run on 2026-09-20T01:13:26Z at revision
cc3d82057f1d5e9aa31f682cee71aabfbbbcaabe-dirty (CLI e3181f5): Express app uploaded a versioned, immutable-cached asset to a published bucket at startup; the CDN URL it returned served the asset publicly. (expires 2027-03-19T01:13:26Z) - canary_run on 2026-09-20T01:13:26Z at revision
cc3d82057f1d5e9aa31f682cee71aabfbbbcaabe-dirty (CLI e3181f5): ample bucket create issued credentials; PutObject and GetObject succeeded through the public S3 endpoint; publish exposed the object through the CDN host with an ETag; unpublish and delete cleaned up. (expires 2027-03-19T01:13:26Z)
Last verified: 2026-09-20T01:13:26Z
Execution binding
MCP tool ample_deploy (registry mcp:ample_deploy), schema hash 876465fce906da0c observed 2026-09-20T01:55:48.667900+00:00 at revision 199ff1dfd526, binding state current, required scopes: servers:write, buckets:write.