ARTICLE

Magento Remote Storage on Amazon S3: Moving Adobe Commerce Media Off the Server Without Breaking Image Resizing

Magento Remote Storage on Amazon S3: Moving Adobe Commerce Media Off the Server Without Breaking Image Resizing

Magento Remote Storage, available since Adobe Commerce 2.4.2, moves pub/media and import/export files to an Amazon S3 bucket using the aws-s3 driver. You enable it with setup:config:set, keep the bucket private, copy existing files with remote-storage:sync, and serve images through nginx or a CDN. Image resizing needs its own plan, because resized cache files are still generated locally.

That last sentence is where most S3 projects go wrong. Moving media to object storage is a short CLI change. Keeping product images fast, keeping the admin usable, and keeping a multi-server cluster consistent afterwards is the real work. This guide covers the setup and then the parts the official pages leave for you to figure out.

Why move Magento media to S3 at all

On a single server, pub/media living on local disk is fine. The problems start when you scale out. Two or more web nodes behind a load balancer all need to see the same product images, the same CMS uploads, and the same import files. The traditional answers are an NFS share or a shared EFS volume, and both add latency and a single point of failure to every image request that misses the CDN.

Object storage removes that shared filesystem. Every node reads and writes the same bucket through the Magento filesystem layer, deployments stop needing to carry media around, and storage grows without resizing disks. Adobe describes the benefits as server-side image resizing and better efficiency for multi-server setups in its AWS S3 remote storage documentation.

It is not free of trade-offs. Every file existence check now becomes a network call, image resizing has to be rethought, and some extensions that write files with native PHP functions will break. If you run a single server with a CDN in front, you may not need it yet.

Setup Media location Multi-node friendly Typical pain point
Local disk, single server pub/media on the web node No Disk growth, backups
NFS or EFS shared volume Network filesystem mounted on all nodes Yes Latency, shared volume as a failure point
Database media storage Magento DB tables Partly Database bloat, slow image delivery
Remote Storage on S3 Private S3 bucket via aws-s3 driver Yes Resize cache, file checks, extension compatibility

What Remote Storage actually stores, and what it does not

The Remote Storage module covers two areas:

  • pub/media: product images, category images, CMS uploads, swatches, and other media.
  • var import and export files: the files used by Magento’s import and export features.

Code, static assets in pub/static, logs, and generated code stay on the server. Static content is still part of your build and deploy, which you would normally ship through a release pipeline for Magento and Hyva, not through S3.

One detail changes how you plan the cluster. Adobe’s documentation states that cached images are generated on the local file system, so pub/media folder permissions stay the same as with local storage. In other words, Remote Storage does not make the image cache disappear. If you rely on Magento’s PHP-based resizing, each node can still build its own resized copies. That is why the image resizing section later in this article matters more than the setup itself.

Prerequisites before you switch

Check these before touching env.php:

  1. Magento 2.4.2 or later. Remote Storage does not exist in earlier versions. Older third-party S3 modules that hooked into database file storage are tied to 2.0 to 2.2 era code and are not a safe path on modern versions.
  2. Database media storage turned off. The two storage modes cannot run together. Set it with bin/magento config:set system/media_storage_configuration/media_database 0.
  3. A private bucket. Adobe strongly discourages public buckets and calls them a serious security risk.
  4. Credentials. Prefer an IAM role attached to the instance. Access key and secret are the fallback for environments where roles are not possible.
  5. An extension audit. Search custom and third-party modules for native file functions such as copy, rename, and file_put_contents pointed at media paths. Adobe’s guidance is to use the Commerce filesystem and DriverInterface instead, because native PHP calls write to local disk, not to the bucket.

The extension audit is the step teams skip. A product feed module, a PDF invoice generator, or an image watermark extension that writes straight to disk will appear to work on one node and then return 404s from the others.

Enabling the aws-s3 driver

For an existing store, the command is setup:config:set. For a new install, the same flags work with setup:install. The required parameters are driver, bucket, and region. Prefix, key, and secret are optional.

bin/magento setup:config:set \
  --remote-storage-driver="aws-s3" \
  --remote-storage-bucket="your-media-bucket" \
  --remote-storage-region="us-east-1" \
  --remote-storage-prefix="production" \
  -n

Leave out --remote-storage-key and --remote-storage-secret when the server uses an IAM role. Use the prefix when one bucket holds media for several environments, so staging and production never write to the same path.

To turn the feature off, set the driver back to file. That is your rollback path, and it only works cleanly if a current copy of media still exists on local disk. Keep the local media directory in place until the bucket has been serving production traffic without errors for a while.

S3-compatible providers and the path style bug

Teams using MinIO, DigitalOcean Spaces, or other S3-compatible storage usually need path-style addressing. There is an open issue worth knowing about: GitHub issue 38684 reports that the path style flag writes a path-style key to env.php while the AWS S3 module reads path_style, so the setting is silently ignored. Reports in that thread reproduce it on 2.4.7. The workaround is to edit the remote_storage block in env.php by hand and set the key the module actually reads.

Moving existing media into the bucket

Once the driver is configured, copy existing files with:

bin/magento remote-storage:sync

Two caveats:

  • It only syncs pub/media. Import and export files in var are not copied. Adobe points to scheduled import and export for that data.
  • It can be slow on large catalogs. Some hosting providers recommend the AWS CLI’s aws s3 sync instead, because it uploads files concurrently. If you go that route, sync both pub/media and var/import_export into the right prefix, then verify object counts before cutover.

A practical sequence for a live store:

  1. Run a bulk copy of media to the bucket a day or two before cutover.
  2. Freeze admin media uploads for the cutover window.
  3. Run a final incremental sync.
  4. Switch the driver, flush cache, and test product pages, category pages, CMS blocks, and the admin product grid.
  5. Keep local media untouched until you are confident you will not roll back.

Serving images from a private bucket

A private bucket means browsers cannot fetch images directly from S3. You need something in between. There are three common patterns.

nginx as a proxy. Adobe’s documentation provides an nginx location block that proxies media requests to S3, strips request bodies and headers, intercepts errors, and hides Amazon response headers such as x-amz-request-id and Set-Cookie. If you authenticate with keys rather than IAM roles, nginx needs the third-party ngx_aws_auth module to sign requests. The nginx.conf.sample that ships with Magento includes a commented S3 line for /media/catalog/ as a starting point.

CloudFront with Origin Access Control. AWS recommends Origin Access Control for restricting S3 access to CloudFront over the older Origin Access Identity. The bucket stays private, the bucket policy grants s3:GetObject only to the CloudFront service principal for your distribution, and browsers only ever talk to the CDN. This is the cleanest answer to the contradiction you will find online, where some guides tell you to make /media/* public and Adobe tells you never to make the bucket public.

Fastly on Adobe Commerce Cloud. On cloud infrastructure you cannot edit nginx, so the proxy pattern is not available. Adobe documents a Fastly setup for S3 that adds a backend integration and VCL snippets for S3 authentication and backend requests.

Delivery pattern Bucket stays private Handles resizing Where it fits
nginx proxy to S3 Yes Only with image_filter added Self-hosted, single region
CloudFront with OAC Yes No, needs resizing upstream or at the edge AWS-hosted stores, global traffic
Public /media/* bucket policy No No Not recommended by Adobe
Fastly with S3 VCL Yes Yes, with Fastly Image Optimization Adobe Commerce Cloud

Image resizing: the part that breaks

Magento’s default behavior is to generate resized product images in PHP and store them in the image cache. With Remote Storage, that cache is still local, so on several nodes you either build duplicate caches or you change the resizing model.

Adobe’s answer is query-parameter resizing at the web server. The Remote Storage image resize guide walks through it:

  1. In the admin, go to Stores, Settings, Configuration, General, Web, Url options, and set Catalog media URL format to Image optimization based on query parameters.
  2. Load nginx’s image filter module with load_module /etc/nginx/modules/ngx_http_image_filter_module.so;.
  3. Add a location block for image extensions that reads width and height from the query string and passes them to image_filter resize.

Magento then outputs original image URLs with size parameters, and nginx resizes on request. Three things the official page does not spell out:

  • image_filter is not built by default. nginx needs to be compiled with the image filter module and libgd. Check your package or build before planning around it.
  • Large originals fail. The module’s image_filter_buffer defaults to 1 MB, and images that exceed it or cannot be processed return a 415 error. Either raise the buffer or define an error_page 415 fallback, and make sure merchandisers are not uploading 8 MB camera files as product images.
  • Resizing on every request is expensive. Without a cache in front, nginx resizes the same image again for each request that misses the CDN. Put a CDN or an nginx proxy_cache in front of the resize location so each size is built once.

Also plan how this interacts with modern formats. If your storefront serves WebP or AVIF, decide whether conversion happens at the CDN, at nginx, or inside Magento, and test that path end to end. Our guide to WebP and AVIF on a Hyva Magento storefront covers the format side of that decision.

What this means for Hyva storefronts

Hyva does not change how Remote Storage works. It renders image URLs that Magento generates, so the query-parameter format and CDN rules apply the same way they do on Luma. What Hyva does make visible is the cost of slow image delivery: a lean frontend means the hero and gallery images are often the largest remaining part of Largest Contentful Paint. After the switch, test your main product image and category tiles under a cold CDN cache. If S3 round trips push LCP up, the fixes in our LCP guide for Hyva storefronts still apply, and teams building rich galleries should read our notes on zoom, video, and 360 spin on Hyva without hurting LCP.

If you use Hyva’s media optimization features that generate responsive variants, test where those variants land and how they are served once Remote Storage is on. Do not assume the behavior; verify it on staging.

The admin slowdown nobody warns you about

After the switch, merchandisers often report that the admin product grid feels slow. The reason is that the grid checks whether each row’s thumbnail exists, and with Remote Storage each check becomes a request to S3. One open source module from a hosting provider, ByteInternet’s remote storage tweaks, targets exactly this by building thumbnail URLs without the existence check. Test the grid with a realistic page size on staging before go-live, and treat any module like this as code you need to review and own.

Adobe Commerce Cloud specifics

On Adobe Commerce Cloud, Remote Storage is configured through the REMOTE_STORAGE variable rather than setup:config:set. The Commerce Cloud remote storage documentation lists the requirements: ece-tools 2002.1.5 or later on Commerce 2.4.2 or later. The variable is read during the deploy phase and can be set in .magento.env.yaml under the deploy stage or as an environment variable.

Practical points from that documentation:

  • Mark the variable as sensitive and not inheritable, so credentials do not leak into child environments.
  • Because it is set per environment, you can turn it on for Production and Staging and leave Integration on local storage.
  • The deploy log confirms the change with a line stating that the remote storage driver is set to aws-s3. After that, run remote-storage:sync over SSH.
  • Adobe describes its support as limited and does not take responsibility for data loss or outages related to a customer-supplied bucket.

IAM and bucket hygiene

Adobe’s documentation does not publish a least-privilege policy, so define one deliberately. Magento needs to read, write, delete, and list objects within its prefix. Scope the policy to the bucket and prefix the store uses, not to all of S3. Keep S3 Block Public Access enabled at the account and bucket level. Turn on versioning so a bad import or a buggy extension that deletes files can be recovered. Add a lifecycle rule for old noncurrent versions so storage does not grow forever.

A go-live checklist

Check How to verify
Database media storage off config value system/media_storage_configuration/media_database is 0
Extensions use the filesystem layer Code search for native file functions on media paths
Bucket private, Block Public Access on S3 console and bucket policy review
Media synced, counts match Compare local file count to bucket object count per prefix
Images load on PDP, PLP, CMS Cold-cache browser test and CDN logs
Resize path cached Repeat request for the same size returns from cache
415 fallback in place Request a resize of an oversized original
Admin grid acceptable Load product grid at production page size
Rollback tested Switch driver to file on staging and confirm pages render

When to bring in help

Remote Storage is a small config change sitting on top of an infrastructure decision. If you run several web nodes, sell across regions, or use extensions you did not write, the risk sits in the details above, not in the CLI flags. Bemeir’s Magento and Adobe Commerce development team handles this kind of infrastructure work alongside our Hyva frontend development services, and we work with the hosting and CDN vendors listed among our technology partners.

For context, hosted SaaS platforms take this problem off the table entirely. Merchants on Shopify or BigCommerce never configure media storage, and Shopware cloud editions handle it for you too. Owning your media layer is part of the control you get with Magento, and it pays off when it is set up properly. You can read more about Bemeir and how we approach platform work, or start at the Bemeir homepage.

FAQ

Which Magento version supports Remote Storage on S3?

Remote Storage was added in Adobe Commerce and Magento Open Source 2.4.2. The documented cloud driver is aws-s3, and the file driver switches the feature back to local storage. On Adobe Commerce Cloud, you also need ece-tools 2002.1.5 or later.

Does remote-storage:sync copy everything?

No. It copies pub/media only. Import and export files in var are not included, so handle those separately, either through scheduled import and export or a direct copy with the AWS CLI.

Should the S3 bucket be public so images load faster?

Adobe strongly discourages public buckets. Keep the bucket private and serve media through an nginx proxy, CloudFront with Origin Access Control, or Fastly on Commerce Cloud. A CDN in front gives you the speed without exposing the bucket.

Why are product images slow or missing after enabling S3?

The usual causes are resized images still being generated locally on each node, nginx resizing without a cache in front, oversized originals returning 415 errors from the image filter, or an extension writing files to local disk instead of the bucket. Check each in that order.

Can I roll back to local storage?

Yes. Set the remote storage driver back to file. Rollback is only safe if local media is complete and current, so keep the local copy until the bucket has run in production long enough to trust it.

Let us help you get started on a project with Magento Remote Storage on Amazon S3: Moving Adobe Commerce Media Off the Server Without Breaking Image Resizing and leverage our partnership to your fullest advantage. Fill out the contact form below to get started.

more articles about ecommerce

Read on the latest with Shopify, Magento, eCommerce topics and more.