Skip to main content

CDN Acceleration and Caching

CDN acceleration, custom domains, and cache configuration in Postgres-Native Cloud Storage are shared with classic-mode Cloud Storage. This page focuses on how to design access, permissions, and caching for Postgres-Native buckets. For full configuration details, see CDN acceleration.

Access flow

After CDN acceleration is enabled, the file access path can be understood as:

User browser


CDN edge node
│ cache hit: return directly
│ cache miss: fetch from origin

CloudBase Storage API / object storage backend

The key value of CDN is to serve files from nearby edge nodes, reducing origin latency and pressure. Cache hit rate depends on whether the URL is stable, whether it can be reused by multiple users, and whether requests carry user-level authorization context.

Public buckets are more cache-friendly

Public assets do not need per-user authorization checks. When many users request the same URL, they are more likely to share the same CDN cache. Typical CDN-friendly assets include:

  • logos, icons, fonts, and frontend static assets;
  • public article images, product images, and campaign banners;
  • public avatars and public media content.

Recommended setup:

ItemRecommendation
BucketUse a dedicated public asset bucket, such as public-assets
PermissionExplicit public-read RLS; only trusted backend or admins can write
URLUse getPublicUrl() to generate stable public URLs
PathUse versioned paths, such as assets/logo.v2.png
CacheSet appropriate cacheControl when uploading
const bucket = app.storage.from('public-assets');

await bucket.upload('assets/logo.v2.png', file, {
contentType: 'image/png',
cacheControl: 'max-age=31536000',
});

const { data } = bucket.getPublicUrl('assets/logo.v2.png');
console.log(data.publicUrl);

Example public-read policy:

CREATE POLICY public_assets_read ON storage.objects
FOR SELECT TO anon, authenticated
USING (bucket_id = 'public-assets');

Public read does not mean public write. In production, avoid opening INSERT / UPDATE / DELETE to anon.

Private buckets usually have lower cache hit rates

Private files are typically accessed with login state, an Authorization header, or a signed URL. Even if two users access the same object, their permission context may differ, so the request is less likely to share CDN cache like a public asset.

Recommendations for private assets:

  • use download() or short-lived createSignedUrl();
  • do not treat signed URLs as long-lived static asset URLs;
  • use shorter expiration for sensitive files;
  • if you need long-lived high cache hit rates, consider whether the file can be moved to a public-resource bucket with explicit public-read RLS.
Access methodCDN friendlinessRecommendation
getPublicUrl()HighPublic, stable, cacheable assets
createSignedUrl()Medium / lowTemporary sharing, not long-lived static asset URLs
download() with login stateLowDirect private file access
Backend download proxyDepends on implementationCentralized auth, audit, and rate limiting

Overwrites and CDN cache

If an object path is already cached by CDN, overwriting that path may still return old content from edge nodes for a while. Similar to Supabase Storage, prefer new paths for new versions instead of frequently overwriting the same path.

Recommended:

assets/logo.v2.png
articles/123/cover-20260614.png
products/sku-001/main-<hash>.jpg

Not recommended:

assets/logo.png # frequently overwritten
articles/123/cover.jpg # frequently overwritten

Use upsert: true for fixed-path resources such as avatars only when cache delay is acceptable. Add a version parameter or update timestamp to the display URL:

const { data } = app.storage
.from('avatars')
.getPublicUrl(`${uid}/avatar.png`);

const avatarUrl = `${data.publicUrl}?v=${profile.updatedAt}`;

Cache-Control recommendations

Use cacheControl together with your path strategy:

Asset typePath strategycacheControl recommendation
Versioned static assetassets/logo.v2.pngLong cache duration is acceptable
Article / product imageVersion, timestamp, or hash in pathLong cache duration is acceptable
AvatarFixed path + URL version parameterMedium cache duration, or business-specific
Private signed URLTemporary URLDo not rely on long-lived cache

If the resource URL stays unchanged, avoid very long cache durations. If you need long caching, make the path itself versioned.

Decision table

RequirementRecommendation
Public static assets with high cache hit ratePublic Bucket + getPublicUrl() + versioned path + long cacheControl
Private attachment only accessible by ownerPrivate Bucket + download() or short-lived createSignedUrl()
Temporarily share a file externallycreateSignedUrl() with short expiration
Image updates must take effect globally immediatelyUse a new path and update business references; do not rely on overwriting old paths
Fixed avatar pathupsert is acceptable, but add a version parameter to the display URL

AI-friendly prompt

Bucket: public-assets
Asset type: public static assets
Access method: getPublicUrl
Path strategy: versioned paths, such as assets/logo.v2.png
Cache strategy: long cache; set cacheControl on upload
Overwrite: not allowed; publish new versions with new paths
Permission: anon/authenticated can read; only service_role can write

This helps AI avoid treating private signed URLs as long-lived CDN URLs, and avoids risky designs such as overwriting the same path with long cache durations.