Storyblok traffic limit reached? How to cut your CDN usage

Storyblok counts every byte it sends, images and API responses alike. Here’s how to find what’s eating your traffic, and the fixes that actually move the number.

StoryblokIntermediate level5 min readLast verified 1 Nov 2026

So Storyblok says your space is close to (or over) its traffic limit. We’ve had this on a few client sites at Undefined, and it’s almost never the content itself. It’s usually a handful of huge images, a video someone uploaded a while ago, or an API call that skips the cache.

The good news: it’s very fixable, and most of it is a one-off.

What counts as traffic

Storyblok counts every byte it sends, cached or not: API responses, asset downloads and every Image Service variation. API requests are counted separately, as a monthly number of calls.

At the time of writing, the plan limits look like this:

  • Starter: 100GB, and that’s the max
  • Growth: 400GB included, up to 1TB with overage
  • Growth Plus: 1TB, no overage

On Starter and Growth, going over costs $75 per extra 250GB, charged as soon as you go over (not at the end of the month). It’s all in Storyblok’s overage fact sheet.

Find what’s using it

Open your space and look at Consumption metrics on the space dashboard. It has tabs for overall traffic, traffic per asset and API traffic, each with a date filter.

The per asset tab is your hit list. Sort by size and the culprits are usually obvious: one image that has been sent a few hundred thousand times at full size, or a video doing the rounds.

Want the whole list, for example to share with the team? The Management API has an assets traffic endpoint that returns the bytes sent per file for a date range:

curl "https://mapi.storyblok.com/v1/orgs/me/statistics/assets_traffic?start_date=2026-10-01&end_date=2026-10-31" \
  -H "Authorization: YOUR_PERSONAL_ACCESS_TOKEN"

Roughly how to read it:

  • A few big images on top: they are being served at full size somewhere. Step 1.
  • Videos or PDFs on top: they should live somewhere else. Step 2.
  • API traffic is high, assets are fine: your site is skipping the cache or fetching more than it needs. Step 3.

Fix it, biggest wins first

  1. 1

    Never serve the original image

    Every asset URL can go through the Image Service: add /m/ and a size, and you get a resized copy instead of the 6MB original someone exported straight from Figma. Smaller files mean less traffic, simple as that.

    <!-- before -->
    https://a.storyblok.com/f/123/4000x2500/abc/hero.jpg
    
    <!-- after: 1200px wide, AVIF, quality 75 -->
    https://a.storyblok.com/f/123/4000x2500/abc/hero.jpg/m/1200x0/filters:format(avif):quality(75)

    Use a srcset with a few widths (say 640, 1200 and 2000) so phones don’t download the desktop version. Every size counts as traffic too, so don’t go overboard with variations.

  2. 2

    Move video to Bunny, keep a URL in Storyblok

    Storyblok’s own docs say to host large files like video yourself. A single background video can easily be more traffic than the rest of the site together.

    What we do on client sites at Undefined: the video goes on Bunny, and the component gets a URL field instead of an asset field.

    • Short muted loops (hero backgrounds, product clips): upload the mp4 to a Bunny storage zone with a pull zone in front. About $0.01/GB in Europe and North America.
    • Longer videos with sound: Bunny Stream, which encodes a few qualities so phones don’t get the 1080p version.
    • In Storyblok: a Text field for the Bunny URL, plus an Asset field for the poster image, so the still frame still goes through the Image Service.
    // video component schema
    "video_url": { "type": "text", "description": "Bunny URL, ends in .mp4" },
    "poster": { "type": "asset", "filetypes": ["images"] }
    
    // rendering it
    <video
      src={blok.video_url}
      poster={`${blok.poster.filename}/m/1600x0`}
      autoPlay muted loop playsInline
    />

    Editors paste a link instead of uploading, and the video never touches your Storyblok traffic. Same trick for big PDFs.

  3. 3

    Make your API calls hit the cache

    Storyblok’s CDN caches published content, keyed on the cv (cache version) parameter. A few things break that:

    • Fetching version=draft in production. Drafts are for the Visual Editor only.
    • Passing cv=Date.now() to get fresh content. Every request becomes a cache miss. Store the latest cv instead and update it from a publish webhook.
    • Fetching fields you never render. Use excluding_fields to drop big ones, and filter queries instead of fetching everything and filtering in the front-end.

    If you build statically, fetch stories in pages of 100 instead of one request per story.

  4. 4

    Put your own CDN in front of your assets

    Storyblok has official guides for a custom assets domain on CloudFront, Azure and Google Cloud, where your CDN pulls from a.storyblok.com. We like Bunny for this: a pull zone costs about $0.01/GB in Europe and North America, and setting one up takes ten minutes.

    • Create a pull zone with https://a.storyblok.com as origin (or your region, like a-us.storyblok.com)
    • Add a hostname like assets.yoursite.com and turn on the free SSL
    • Turn on Origin Shield, so a cache miss is one request to Storyblok instead of one per location
    • Swap the host in your image URLs. The resize part is in the path, so it caches as is.

    Each image still comes from Storyblok once per cache miss, but every repeat after that comes from Bunny. If you use plain /m/ (WebP when the browser supports it), either add an explicit format() filter or turn on Vary cache → WebP in Bunny, otherwise everyone gets whichever version was cached first.

Checklist

See every image your content uses

Paste your URL. Cojack syncs your whole space, so you can search every image and see which stories use it. Handy for tracking down that 12MB hero.

Questions you asked

QDo cached responses still count as traffic?

Yes. Storyblok counts every byte it sends, cached or not. Caching helps with speed and API limits, but for traffic it’s the size of what you send that matters.

QWon’t resizing images create more traffic?

Each variation counts, but a 150KB WebP instead of a 4MB JPEG is a massive saving. Stick to a few standard widths and it more than pays for itself.

QDoes a CDN in front stop all Storyblok traffic?

No. Every cache miss still pulls the file from Storyblok once. With Origin Shield and decent cache times that’s a tiny share of what you had.

QCan I set up usage alerts?

Not in the dashboard at the time of writing. Put a monthly reminder in your calendar to check Consumption metrics, or pull the assets traffic endpoint into a small script.