惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

G
Google Developers Blog
Jina AI
Jina AI
大猫的无限游戏
大猫的无限游戏
Martin Fowler
Martin Fowler
博客园 - 司徒正美
云风的 BLOG
云风的 BLOG
C
Cybersecurity and Infrastructure Security Agency CISA
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
S
Securelist
S
Security Affairs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
L
LINUX DO - 热门话题
博客园 - 三生石上(FineUI控件)
T
Threatpost
T
The Blog of Author Tim Ferriss
C
CERT Recently Published Vulnerability Notes
IT之家
IT之家
P
Palo Alto Networks Blog
Microsoft Azure Blog
Microsoft Azure Blog
Spread Privacy
Spread Privacy
Cyberwarzone
Cyberwarzone
腾讯CDC
L
LangChain Blog
Know Your Adversary
Know Your Adversary
C
CXSECURITY Database RSS Feed - CXSecurity.com
GbyAI
GbyAI
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
I
Intezer
T
Tor Project blog
AWS News Blog
AWS News Blog
T
Tenable Blog
NISL@THU
NISL@THU
Security Latest
Security Latest
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
H
Hackread – Cybersecurity News, Data Breaches, AI and More
人人都是产品经理
人人都是产品经理
MongoDB | Blog
MongoDB | Blog
MyScale Blog
MyScale Blog
D
DataBreaches.Net
Microsoft Security Blog
Microsoft Security Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
量子位
美团技术团队
The Cloudflare Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
罗磊的独立博客
The GitHub Blog
The GitHub Blog
阮一峰的网络日志
阮一峰的网络日志
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Stack Overflow Blog
Stack Overflow Blog

Supabase Blog

AI Agents Know About Supabase. They Don't Always Use It Right. Custom OIDC Providers for Supabase Auth 100,000 GitHub stars Supabase docs over SSH Navigating Regional Network Blocks Supabase Joins the Stripe Projects Developer Preview Log Drains: Now available on Pro Supabase Storage: major performance, security, and reliability updates Supabase incident on February 12, 2026 Hydra joins Supabase X / Twitter OAuth 2.0 is now available for Supabase Auth BKND joins Supabase Supabase is now an official Claude connector Supabase PrivateLink is now available Introducing: Postgres Best Practices When to use Read Replicas vs. bigger compute Introducing TRAE SOLO integration with Supabase Supabase Security Retro: 2025 Sync Stripe Data to Your Supabase Database in One Click Building ChatGPT Apps with Supabase Edge Functions and mcp-use Own Your Observability: Supabase Metrics API Introducing iceberg-js: A JavaScript Client for Apache Iceberg Introducing Supabase for Platforms Adding Async Streaming to Postgres Foreign Data Wrappers Build "Sign in with Your App" using Supabase Auth Introducing Seven New Email Templates for Supabase Auth The new Supabase power for Kiro Introducing Supabase ETL Introducing Analytics Buckets Introducing Vector Buckets Snap, Inc. Launches Snap Cloud, Powered by Supabase Triplit joins Supabase Supabase Series E 1000 Y Combinator Founders Choose Supabase gm 👋 web3, welcome aboard to Sign in with Web3 (Solana, Ethereum) Announcing the Supabase Remote MCP Server Enterprise speed, enterprise standards with Bolt Cloud + Supabase PostgREST 13 Lovable Cloud + Supabase: The Default Platform for AI Builders Processing large jobs with Edge Functions, Cron, and Queues Defense in Depth for MCP Servers OrioleDB Patent: now freely available to the Postgres community Supabase Launch Week 15 Hackathon Winner Announcement The Vibe Coder's Guide to Supabase Environments Testing for Vibe Coders: From Zero to Production Confidence The Vibe Coding Master Checklist Vibe Coding: Best Practices for Prompting Supabase Auth: Build vs. Buy Top 10 Launches of Launch Week 15 Supabase Launch Week 15 Hackathon Storage: 10x Larger Uploads, 3x Cheaper Cached Egress, and 2x Egress Quota Persistent Storage and 97% Faster Cold Starts for Edge Functions Algolia Connector for Supabase New Observability Features in Supabase Improved Security Controls and A New Home for Security Introducing Branching 2.0 Stripe-To-Postgres Sync Engine as standalone Library Supabase Analytics Buckets with Iceberg Support Create a Supabase backend using Figma Make Introducing JWT Signing Keys Supabase UI: Platform Kit Build a Personalized AI Assistant with Postgres Announcing Multigres: Vitess for Postgres Building on open table formats Open Data Standards: Postgres, OTel, and Iceberg Simplifying back-end complexity with Supabase Data APIs PostgreSQL Event Triggers without superuser access Top 10 Launches of Launch Week 14 Supabase MCP Server Data API Routes to Nearest Read Replica Declarative Schemas for Simpler Database Management Realtime: Broadcast from Database Keeping Tabs on What's New in Supabase Studio Edge Functions: Deploy from the Dashboard + Deno 2.1 Automatic Embeddings in Postgres Introducing the Supabase UI Library Supabase Auth: Bring Your Own Clerk Postgres Language Server: Initial Release Migrating from Fauna to Supabase Migrating from the MongoDB Data API to Supabase Dedicated Poolers Postgres as a Graph Database: (Ab)using pgRouting AI Hackathon at Y Combinator Calendars in Postgres using Foreign Data Wrappers Supabase Launch Week 13 Hackathon Winners How to Hack the Base! Running Durable Workflows in Postgres using DBOS database.build v2: Bring-your-own-LLM Restore to a New Project Hack the Base! with Supabase Top 10 Launches of Launch Week 13 Supabase Queues High Performance Disk Supabase Cron Supabase CLI v2: Config as Code Supabase Edge Functions: Introducing Background Tasks, Ephemeral Storage, and WebSockets Supabase AI Assistant v2 OrioleDB Public Alpha Executing Dynamic JavaScript Code on Supabase with Edge Functions ClickHouse Partnership, improved Postgres Replication, and Disk Management
Supabase Storage v2: Image resizing and Smart CDN
Fabrizio Fenoglio, Inian Parameshwaran · 2022-12-13 · via Supabase Blog

Today we're introducing three new features for Supabase Storage: Image resizing, webhooks, and a Smart CDN.

These features are designed to work together to deliver a next-gen image resizing system. Let's explore how it works.

Image resizing has been a popular request since we released Supabase Storage. For good reason - if you're providing an image upload function to your users, you can't expect them to optimize the images before uploading.

Supabase developers have been hacking together all sorts of workarounds using client-side compression, or external providers like Cloudinary and Imgix.

Today's release changes that. Resizing is now as easy as adding a few lines of code:


_10

supabase.storage.from('bucket').getPublicUrl('image.jpg', {

_10

transform: {

_10

width: 500,

_10

height: 600,

_10

},

_10

})


Choosing a resizer#

Supabase Storage uses imgproxy. As usual, we assessed various open source tools available, including Imaginary (MIT) and Sharp (Apache2).

All of these have very friendly open source licenses for self-hosting, so ultimately it came down to features and performance.

While Imaginary doesn't support some modern image formats yet (like AVIF), Sharp and imgproxy are both very feature-complete and well-maintained

In a head-to-head benchmark, we found the performance to be almost identical, with the deciding factor instead coming down to resources.

Developer Experience#

We spent a long time considering what a good developer experience would be for image resizing.

We landed on a simple, on-demand interface. Downloading a resized image in JavaScript looks like this:


_10

supabase.storage.from('bucket').download('image.jpg', {

_10

transform: {

_10

width: 800,

_10

height: 300,

_10

resize: 'contain', // 'contain' | 'cover' | 'fill'

_10

},

_10

})


Or you can make a direct request to the Storage API (see width and height params):


_10

GET https://project_id.supabase.co/storage/v1/render/image/public/bucket/image.jpg?width=500&height=600


If you've never used a resizing service before, you might be interested to learn that there are various approaches. Some services require you to resize your images “server side” before you can download them in the browser. Other services allow you to resize directly from the client. We opted for this client-based approach. It feels more developer friendly.

We might additionally launch server-side presets as we add transformations because they provide a good DX for chaining multiple transformations (resize, rotate, and watermark for example). With server-side presets, transformations can be bundled together into a single command - ?preset=profile instead of adding ?width=200&rotate=90&watermark=image to all your image URLs.

Behind the scenes, we've provided a few small niceties:

  • No footguns: an image will never be resized bigger than original dimensions (even if the user specifies larger dimensions)
  • Sane defaults: default mode maintains aspect ratio and the resize mode is cover
  • Standardization: resize modes mirror the object-fit property of CSS. We support the contain, cover and fill modes.

Image Resizing is in Beta. While in Beta, it is only enabled for Pro Plan and Enterprise customers.

Resizing images can get expensive, so before this release we knew we needed a better caching system. We already provide a “basic” CDN for all projects (including Free Plan), so the important update here is some smarter cache invalidation whenever there are changes.

Our Basic CDN works by adding a 1-hour cache header to every request. After this header expires, we re-check the origin (S3), to see if an image is still available. This parameter is configurable (for example, you can make it one day, or one year).

This approach introduces the possibility of a “stale” image. If you update an image in S3, users will continue to see the old, stale image for one hour. Similarly for deleted images - the cache will continue serving the deleted image until the cache expires.

With this release we're introducing a Smart CDN. Whenever you update or delete an image, the cache will be busted within 60 seconds - for every region in the world.

As a developer, you no longer need to worry about adjusting your cache parameters - the cache “just works”.

If you're interested in how the cache works, see the deep-dive later in this blog post.

As a “pre-release”, we've added webhooks and rate-limiting to the Storage API. We haven't exposed these parameters on our platform yet, but they are coming soon.

If you're self-hosting then you can use them today. It's as simple as enabling a few environment variables.

The webhook events we added are:


_10

ObjectCreated:Post # A new object is created

_10

ObjectCreated:Put # A new object is updated

_10

ObjectCreated:Copy # An object is duplicated

_10

ObjectCreated:Move # An object is created as part of a move operation

_10

ObjectRemoved:Delete # An object is deleted

_10

ObjectRemoved:Move # An object is deleted as part of a move operation

_10

ObjectUpdated:Metadata # An object's metadata is updated


Let's put everything together to see how the new Smart CDN works with Imgproxy.

Some developers have a high “resize” workload, and some have a high “read” workload. This means that there are different scaling requirements for every developer. As a result, we kept the image resizer and the Storage API as two separate containers. This allows them to scale independently depending on your workload.

Let's step through a few different flows to see how it all works:

  • Cache miss: the image has never been resized
  • Cache hit: the image has been resized and is stored in the cache
  • Cache refresh: an image is updated/deleted and the CDN needs to be updated

Cache miss#

Let's imagine one of your users makes a request for a resized cat (kitten?) image in your application. Here's the flow:

  1. The request hits our globally-distributed API Gateway. This gateway reads the image metadata from a global KV store (this metadata is created when the image was uploaded).
  2. Inside the image metadata is a Cache Key - this is comprised of an Etag + tenant ID + bucketname + image name. The Gateway tries to find a cached object in our CDN using the Cache Key. If the image has never been accessed, it is a “Cache miss”.
  3. The request falls back to the Storage server. Because this is a resize request, it is forwards a short-lived S3 URL to Imgproxy.
  4. Imgproxy resizes the image and returns it to the Storage Server which in then returns it to the API Gateway, with stores it in the Cache (which means that the next time the Etag is checked, the result will return directly from the cache).

Cache hit#

The cat image goes viral, and so now multiple users want to see the resized image.

  1. The request hits our globally-distributed API Gateway. This gateway reads the image metadata from a global KV store.
  2. Using the Cache Key the Gateway tries to find a cached object in our CDN. Because this image has already been resized, it returns it directly from the cache.

Cache refresh#

To complete this architecture, we need to keep the global KV store (which stores the image metadata) synchronized whenever an image is changed. To avoid coupling any CDN-specific logic into the Storage server, we added Webhooks that publish events for every object created, updated and deleted.

Using our cat picture from above:

  1. You update the cat picture to a dog picture. This triggers an ObjectCreated:Put event from the Supabase Storage server.
  2. A cache manager service subscribes to these events and updates the global metadata store with the new Etag. This takes around 60 seconds to propagate globally.
  3. The next time there is a request for the resized image, it will be a cache miss.

Most CDNs offer this functionality “natively”. However there is usually a hard-limit to the number of daily cache purges. This implementation gives us greater control over when the cache is cleared.

The impact#

Besides solving issues with stale data, one of the biggest benefits this architecture offers is higher cache hits. Why is that important? Because image resizing is slow. Every cache miss is increased latency for your users.

The green line here shows the number of cache hits to our CDN. As you can see, when we enabled the Smart CDN, the number of requests cache hits increased significantly (which means faster cat images).

Image Resizing is in Beta. While in Beta, it is only enabled for Pro Plan and Enterprise customers.

When choosing a pricing model there were a few options that competitors offered:

  • Pay for every transformation, but don't pay for a CDN hit
  • Don't pay for transformations, but pay for every request (even if it's a CDN hit)

We tried to find a middle ground, where you pay for the number of images you want to transform rather than the number of transformations:

  • You can transform 100 images per project, at no additional cost. Beyond this, it is $5 per additional 1000 images transformed.
  • Each image can be transformed up to 20 times. This is based on fair-usage. If you exceed the limit, we won't return an error and your site will continue to function (but you will get a sternly-worded email from @AntWilson).

Of course, all of this functionality is free in the self-hosting setup too. You can self-host the Storage API either as a standalone service or as part of the Supabase stack.

For local development, this is available in our CLI from v1.23.0.

Upgrade to supabase-js v2.2.0.

A few features to look out for in the future:

  • Webhooks: we'll expose all Storage webhooks and events so that you can consume them from your own services.
  • More Transformations: quality, rotate, blur? Cast your vote on this GitHub Discussion.
  • Integrations: Native integration with next/image and Edge Functions for advanced transformations.

Upgrade to Pro to get started with Image Resizing today.