Staging Sites, Dev Environments,
and Media: The Sync Problem Nobody Solves
Every developer working on a live WordPress site has dealt with the staging media problem. You push the database to staging and half the images are broken. You set up a local dev environment and thumbnails are missing. You deploy to production and the media you added in staging is gone. Here is why this keeps happening and how FTP offload solves it structurally.
Updated 2026
WordPress Dev Workflow Guide

Every WordPress developer who works on live sites has encountered some version of the same media synchronization problem. You pull a database backup to a staging environment to test a redesign, and product images are broken throughout the site because the uploads directory on staging does not match what the database references. You set up a local development environment and spend an hour copying gigabytes of image files before you can see the site render correctly. You add a new product image on staging, push the database to production, and discover the image does not exist on the production server.
These problems are so common that most developers have simply accepted them as an inevitable part of the WordPress development workflow. Image migration tools, rsync scripts, and hosting-provider staging features all attempt to patch the symptom without addressing the cause. The cause is structural: when media files are on the hosting server, every environment that runs the same WordPress installation needs its own separate copy of those files, and keeping those copies in sync is a permanent operational burden.
FTP offloading with CDN delivery eliminates the structural cause. When all media lives on a single FTP server outside any specific hosting environment, every environment — production, staging, local development, QA — can reference the same media library through the same CDN URLs without any file copying. The sync problem does not need to be solved because the synchronization requirement no longer exists.
The three staging media problems and their structural cause
WordPress staging media problems all stem from one root cause: the database references images by their paths in the uploads directory, but the physical files in that directory are on the hosting server, not in the database. When you move the database without the files, the references break. When you move files without updating the database, the references still break but for a different reason.
You push a database snapshot to your staging server to test a theme update. The staging server has a fresh WordPress installation with an empty uploads directory. The database contains thousands of attachment records referencing paths like /wp-content/uploads/2024/product-image.jpg. Those files do not exist on the staging server. Every product image, every featured image, every gallery image is broken. The site is visually unusable for testing anything that involves content.
A content editor uploads new product images to the staging site during a design review. After approval, the database is pushed to production. The new attachment records are now in production’s database but the image files are on the staging server’s uploads directory. Production shows broken images for all the newly uploaded content, and the content editors have to re-upload everything on the production site.
Setting up a local development environment for a mature WordPress site with a large media library requires either copying all the media files locally (slow, disk-intensive, and must be refreshed periodically) or working with a site full of broken images (makes front-end development practically impossible for layout and visual work). Neither option is satisfactory. Large agencies with multiple developers multiply this problem: each developer needs their own local copy of the media library, all diverging from production over time.
How FTP offload changes the staging media relationship
When media is offloaded to an external FTP server and served via CDN, the relationship between the WordPress installation and its media fundamentally changes. Instead of media files being physically co-located with each WordPress environment, all environments reference media through CDN URLs that resolve to the same FTP server regardless of which environment the reference originates from.
The database still contains attachment records with path references, but WP FTP Media’s URL rewriting transforms those paths to CDN URLs at render time. When the staging site renders a product page, it rewrites all image paths to CDN URLs pointing at the same FTP storage as production. The images load from CDN correctly on staging without any files being copied to the staging server. The same is true for local development: configure WP FTP Media to use the production CDN URL in the local environment, and all images load from CDN without any local file copying.
Before FTP offload: Media lives on the production hosting server. Every other environment needs a copy.
After FTP offload: Media lives on the FTP server, outside any specific hosting environment. Every environment references the same media through the CDN URL without needing a local copy. The media library has no “home environment” — it is shared infrastructure that all environments consume.
This shift eliminates synchronization as a problem category rather than solving it case by case.
The exact WP FTP Media configuration for each environment
The multi-environment setup requires slightly different WP FTP Media configurations for each environment type. Here is exactly what to configure where.
Protocol: SFTP
Remote Root: /wp-content/uploads/
CDN Base URL: https://cdn.yoursite.com
Auto Upload: ENABLED
Delete Local After Upload: ENABLED
Production is the authoritative environment. Auto upload is on. Local deletion is on. Every new upload on production goes immediately to FTP and is served from CDN. The production uploads directory stays empty.
Protocol: SFTP
Remote Root: /wp-content/uploads/
CDN Base URL: https://cdn.yoursite.com
Auto Upload: ENABLED (staging uploads go to same FTP)
Delete Local After Upload: ENABLED
Staging uses the same FTP connection and CDN URL as production. Images uploaded on staging go to the same FTP server as production images, which means they will be available on production immediately after the database push — no separate file transfer needed. The staging site renders all existing production images correctly without any file copying.
Protocol: SFTP
Remote Root: /wp-content/uploads/
CDN Base URL: https://cdn.yoursite.com
Auto Upload: DISABLED (local uploads stay local)
Delete Local After Upload: DISABLED
Local dev uses the same CDN URL so all existing production images render correctly in the local browser (the browser fetches them from the production CDN). Auto upload is disabled so that test images uploaded during local development do not pollute the production FTP library. Local uploads stay local until the developer intentionally pushes them to the FTP server.

Handling images uploaded on staging: the deployment workflow
With the shared FTP configuration described above, images uploaded on staging go directly to the production FTP server. When the staging database is pushed to production, the attachment records for those images already reference files that exist on the FTP server. Production renders them correctly without any additional file transfer.
This is the key workflow improvement: database push becomes the complete deployment action. Previously, a staging-to-production deployment involved pushing the database and then separately transferring all new media files. With shared FTP, the database push is the only required step. The media was already on the shared FTP server when it was uploaded on staging.
2. Import to production
3. rsync staging uploads to production
4. Fix broken image references if paths differ
5. Verify images load on production
6. Fix any remaining broken references
Total time: 45 to 120 minutes
2. Import to production
3. Verify images load on production
Total time: 5 to 10 minutes
The local development workflow in practice
For local development, the shared FTP approach means you can set up a fully functional local WordPress environment without copying any media files to your local machine. Here is what that workflow looks like in practice.
Clone the production WordPress installation (WordPress core, themes, plugins), import the production database, install WP FTP Media if not already present, configure the CDN base URL to point at the production CDN domain, set auto upload to disabled. The local environment now renders all production images correctly from the CDN. No file copying required. Setup time: 5 to 10 minutes instead of 30 to 90 minutes.
Images you upload locally stay on the local machine (auto upload disabled). For visual testing with real images, you are working with the production media library served from CDN. For testing new image uploads, you test locally and then push those specific files to the FTP server when ready to include in staging or production. This separation keeps the production FTP library clean from test uploads.
In a team context, each developer sets up their local environment using the same CDN URL. Every developer’s local environment renders all production images correctly from CDN without any files on their local machine. When a developer refreshes their local database from production, the media library is automatically up to date because it was always pointing at the shared CDN URL. No more “my local images are 3 months out of date” situations.

Edge cases and how to handle them
The shared FTP approach works cleanly for the most common scenarios. A few edge cases require specific handling.
WordPress stores some image references as absolute URLs in the database. When you push a staging database to production or vice versa, a search-and-replace on the domain is typically required using WP-CLI’s search-replace command or a database migration plugin. Because WP FTP Media uses output-based URL rewriting rather than stored CDN URLs in the database, the domain difference only affects WordPress’s internal domain references, not the CDN image URLs, which are always rewritten correctly at render time regardless of the WordPress domain setting.
If staging is used to preview client work before it is approved for production, you may not want staging images to be publicly accessible from the production CDN. In this scenario, use a separate FTP subdirectory for staging (e.g., /staging/ instead of /wp-content/uploads/) and a separate CDN pull zone for the staging environment. Staging images go to the staging directory and are served from the staging CDN subdomain. Only after approval are they moved to the production directory and become accessible from the production CDN.
When developing without internet access (on a plane, in an area with poor connectivity), the CDN images will not load. For this scenario, a local image placeholder setup using a WordPress plugin that substitutes placeholder images when the CDN is unreachable provides a workable fallback. Alternatively, keeping a small subset of commonly used images in the local uploads directory for offline-only development allows layout work without CDN access.
According to Local by Flywheel’s WordPress development best practices guide, media synchronization is consistently cited as one of the most time-consuming aspects of working across multiple WordPress environments. The shared FTP approach described in this guide directly addresses the root cause of that time consumption by eliminating the synchronization requirement rather than trying to automate it.
WP FTP Media’s multi-environment WordPress media management plugin provides the configuration flexibility to support production, staging, and local dev environments simultaneously from a single FTP storage server and CDN, turning what was a recurring workflow bottleneck into a one-time configuration step.

Stop syncing files between environments. Share one media library instead.
WP FTP Media lets production, staging, and local dev share one FTP media library through CDN delivery, eliminating uploads directory synchronization entirely and reducing staging deployments from a multi-step file transfer to a single database push.

Hey everyone. Just wanted to share my experience with this. I've been using staging sites for years, and the media sync issue is still a pain. pushed a database to staging last week, and sure enough, half the images were broken. The staging server had a fresh install with an empty uploads folder, so of course the references didn't match. it's frustrating because this feels like something that should be solved by now. The workaround tips here are helpful, but I'm still waiting for a real fix. anyone else dealing with this regularly?
Wasted so much time copying images locally
Why do images break when I move just