Editor & Writing·4 min read·

How does VeloCMS store and serve images?

Images upload to Cloudflare R2 object storage and are served through Cloudflare's global CDN with automatic WebP conversion and responsive srcset generation.

VeloCMS stores uploaded images in Cloudflare R2 object storage and serves them through Cloudflare's global edge network. Images are automatically converted to WebP for browsers that support it, resized to responsive breakpoints, and cached at Cloudflare's CDN so they load fast from any country without your blog server handling the bandwidth.

Why does VeloCMS use Cloudflare R2 instead of a typical server?

Storing media on your application server creates several problems: the server disk fills up over time, images need to be replicated if you add more server instances, and every image request hits your application server and consumes bandwidth you're paying for. R2 sidesteps all of this. It's an S3-compatible object store with zero egress fees (unlike AWS S3 where bandwidth costs add up quickly), and because it's integrated with Cloudflare's CDN the files are cached at edge locations worldwide. An image uploaded by a blogger in the UK is cached at Cloudflare's Singapore edge node automatically, so a reader in Singapore gets the image in milliseconds from a nearby server rather than crossing the Atlantic.

How does the automatic WebP conversion work?

When a browser requests an image from your blog, the request includes an Accept header listing which image formats it supports. Cloudflare's Image Resizing feature (active on all VeloCMS tenants with a custom domain or via our shared CDN) reads this header. If the browser supports WebP, Cloudflare serves a WebP version of the image generated on the fly from the original upload. If the browser doesn't support WebP (a small and shrinking minority, mostly older Safari and IE versions), it gets the original JPEG or PNG. The WebP conversion happens at the CDN edge and is cached, so the transformation cost is paid once and subsequent requests get the cached converted file.

What are the image size limits and storage quotas?

Individual image uploads are limited to 20 MB per file for standard image formats (JPEG, PNG, WebP, GIF, SVG). Videos uploaded to the media library are limited to 500 MB per file. Total storage quota depends on your plan: Pro gets 5 GB, Business gets 25 GB, Agency gets 100 GB. You can check your current usage in Admin → Settings → Storage. If you need more storage than your plan includes, the Agency add-on can extend the quota or you can self-host the PocketBase + R2 instance with your own Cloudflare R2 bucket for unlimited storage at Cloudflare's pay-per-GB rate.

Can I use my own CDN or image hosting instead?

On the self-hosted version of VeloCMS you can configure any S3-compatible object store as the media backend — Backblaze B2, AWS S3, MinIO, or your own R2 bucket with custom credentials. The VeloCMS image pipeline will upload to your bucket rather than the shared platform R2 bucket. On SaaS plans (velocms.org subdomain or Cloudflare for SaaS custom domain) the R2 setup is managed for you and can't be changed to a different provider, but you can still reference external image URLs from the editor instead of uploading to R2 if you want to host specific images elsewhere.

Because images are served from Cloudflare's CDN rather than your blog's server, image-heavy posts don't slow down your server or consume your server's bandwidth quota. The cost of serving a post with 20 high-resolution photos is the same as serving a text-only post from the application server's perspective.