Complete guide to WordPress staging sites. Create staging environments, push to production, deploy locally with WP-CLI, git, and CI/CD pipelines.
EN

WordPress staging site workflow: from local development to production deployment

4.80 /5 - (97 votes )
Last verified: May 1, 2026
15min read
Guide
Full-stack developer

Every WordPress site, from a personal blog to an enterprise-grade WooCommerce store, needs a staging environment. Making changes directly on a live website is the single biggest source of preventable downtime in the WordPress ecosystem. A staging site gives you a private copy of your production environment where you can test updates, debug problems, and develop new features without any risk to your visitors.

This guide walks you through every practical approach to creating a staging site, pushing staging to live safely, and building a professional deployment pipeline that scales from a single site to dozens of client projects.

#Why every WordPress site needs a staging environment

The WordPress admin dashboard makes it tempting to click “Update” on plugins and themes without a second thought. But a single incompatible plugin update can break your site layout, crash WooCommerce checkout, or even trigger a white screen of death. On a live site, that means lost revenue and damaged trust.

A staging environment solves this by providing:

  • Safe testing ground - try plugin updates, PHP version upgrades, and theme changes without touching production.
  • Client review space - let clients approve design changes on a real WordPress instance before anything goes live.
  • Development workspace - build custom functionality, test REST API integrations, and experiment with new blocks in isolation.
  • Rollback safety net - if something breaks in staging, production is untouched. If something breaks after deployment, you have a known-good state to revert to.

Professional WordPress agencies treat staging as a non-negotiable part of every project. The time you invest in setting up a proper workflow pays for itself the first time it prevents a production outage.

#Hosting-level staging: the fastest path

Most managed WordPress hosts now include staging environments as a built-in feature. This is the easiest approach for site owners who want staging without touching the command line.

#Kinsta

Kinsta provides a one-click staging environment for every site in the MyKinsta dashboard. It creates a complete clone of your production site, including files and database, on a separate subdomain. When you are ready, the “Push to Live” button lets you deploy the entire staging environment or selectively push only files or only the database.

#WP Engine

WP Engine offers three environments per install: Development, Staging, and Production. You can copy data between environments in either direction. Their system handles the URL rewriting automatically, so database references to your production domain are updated when copying to staging and back.

#Cloudways

Cloudways provides staging through its “Pull” and “Push” operations. You clone your production application to a staging server, make changes, and then push the changes back. Cloudways handles the file synchronization and database migration between environments.

#Limitations of hosting-level staging

While hosting staging tools are convenient, they have constraints. You are locked into that host’s workflow. Database merges can be unpredictable if content editors are actively publishing on production while you work on staging. And most hosts do not support branching, multiple staging environments, or automated deployment triggers. For more control, you need plugin-based or manual approaches.

#Plugin-based staging: no SSH required

If your host does not offer staging, or you need a more flexible solution, several WordPress plugins can create and manage staging environments directly from the admin dashboard.

#WP Staging

WP Staging is the most popular staging plugin in the WordPress repository. The free version creates a staging clone in a subdirectory of your existing hosting account. The Pro version adds the ability to push staging changes back to production.

To create a staging site with WP Staging:

  1. Install and activate the WP Staging plugin from the WordPress repository.
  2. Navigate to WP Staging in the admin sidebar and click “Create Staging Site.”
  3. Select which database tables and folders to include in the clone.
  4. Click “Start Cloning” and wait for the process to finish.

The staging site will be accessible at yourdomain.com/staging (or whatever subdirectory name you chose). The plugin automatically adds basic authentication and noindex headers to the staging copy.

#BlogVault

BlogVault takes a different approach by creating the staging site on their own infrastructure. This means staging does not consume your production server resources. BlogVault handles backups, staging creation, and one-click merges. It is particularly useful for sites on shared hosting where server resources are limited.

#When plugins fall short

Plugin-based staging works well for content-focused sites with occasional updates. But for sites with continuous development, custom plugins, or complex deployment requirements, you will eventually outgrow the plugin approach. That is where manual staging with SSH and WP-CLI becomes essential.

#Manual staging via SSH and WP-CLI

Manual staging gives you complete control over every aspect of the process. This is the approach used by professional WordPress developers and agencies managing multiple client sites.

#Prerequisites

Before starting, make sure you have:

  • SSH access to both your production and staging servers
  • WP-CLI installed on both servers
  • A staging subdomain configured (e.g., staging.yourdomain.com)
  • Matching PHP versions on both environments

#Step 1: sync files with rsync

Use rsync to copy your WordPress files from production to the staging server. The --exclude flags prevent copying environment-specific files that should differ between staging and production:

rsync -avz --delete \
  --exclude='wp-config.php' \
  --exclude='.htaccess' \
  --exclude='wp-content/cache/' \
  --exclude='wp-content/uploads/wpo-cache/' \
  --exclude='wp-content/debug.log' \
  production:/var/www/html/ \
  staging:/var/www/staging/

The --delete flag ensures that files removed from production are also removed from staging, keeping the two environments in sync.

#Step 2: export and import the database

Export the production database with mysqldump and import it into the staging database:

# Export production database
mysqldump -u db_user -p production_db > production_backup.sql

# Import into staging database
mysql -u staging_user -p staging_db < production_backup.sql

Alternatively, use WP-CLI to handle the export and import in a single pipeline:

# Export from production, pipe directly to staging
wp db export --ssh=production - | wp db import --ssh=staging -

#Step 3: search-replace URLs in the database

This is the most critical step. WordPress stores absolute URLs throughout the database, in posts, options, widget data, and serialized arrays. A simple SQL find-and-replace will corrupt serialized data. WP-CLI’s search-replace command handles serialized data correctly:

wp search-replace 'https://yourdomain.com' 'https://staging.yourdomain.com' \
  --all-tables \
  --precise \
  --recurse-objects \
  --skip-columns=guid

Key flags explained:

  • --all-tables searches every table, including those created by plugins.
  • --precise enables a more thorough replacement in serialized data.
  • --recurse-objects handles deeply nested serialized objects.
  • --skip-columns=guid leaves the GUID column unchanged, as WordPress documentation recommends.

#Step 4: flush caches and verify

After the migration, flush all caches to ensure the staging site loads fresh data:

wp cache flush
wp rewrite flush
wp transient delete --all

Open the staging site in a browser and verify:

  • The homepage loads correctly with the staging URL.
  • Internal links point to the staging domain.
  • Media files load properly.
  • Forms and checkout flows function as expected.

#Pushing staging to production safely

When your staging changes are tested and approved, you need to push them to production without downtime. The process is essentially the reverse of creating the staging site, but with additional safety measures.

#Pre-deployment checklist

Before pushing staging to live:

  1. Create a production backup - always have a rollback point.
  2. Put production in maintenance mode - prevents database conflicts from concurrent user activity.
  3. Notify stakeholders - let the team know a deployment is happening.
  4. Schedule during low traffic - minimize impact on real visitors.

#Deploy files

Sync the changed files from staging to production, again excluding environment-specific configuration:

# Enable maintenance mode
wp maintenance-mode activate --ssh=production

# Sync files from staging to production
rsync -avz --delete \
  --exclude='wp-config.php' \
  --exclude='.htaccess' \
  --exclude='wp-content/cache/' \
  --exclude='wp-content/uploads/wpo-cache/' \
  staging:/var/www/staging/ \
  production:/var/www/html/

#Deploy the database

If your staging changes include database modifications (new pages, updated options, plugin settings), export and import the staging database into production:

# Export staging database
wp db export --ssh=staging staging_export.sql

# Import into production
wp db import --ssh=production staging_export.sql

# Search-replace back to production URL
wp search-replace 'https://staging.yourdomain.com' 'https://yourdomain.com' \
  --all-tables \
  --precise \
  --recurse-objects \
  --skip-columns=guid \
  --ssh=production

#Post-deployment tasks

After the database import and search-replace:

# Flush all caches
wp cache flush --ssh=production
wp rewrite flush --ssh=production
wp transient delete --all --ssh=production

# Disable maintenance mode
wp maintenance-mode deactivate --ssh=production

Verify the production site immediately. Check the homepage, key landing pages, checkout flow, and contact forms. Monitor your error logs for the first 30 minutes after deployment.

#Database search-replace deep dive

The WP-CLI search-replace command is one of the most powerful tools in the WordPress deployment toolkit. Beyond basic URL replacement, it handles several critical scenarios.

#Dry run first

Always run a dry run before executing a search-replace on production:

wp search-replace 'https://staging.yourdomain.com' 'https://yourdomain.com' \
  --all-tables \
  --dry-run

The dry run output shows exactly how many replacements will be made in each table, without modifying any data. Review this output carefully before running the real command.

#Handling multisite

For WordPress multisite installations, add the --network flag and replace URLs for each site individually:

wp search-replace 'staging.yourdomain.com' 'yourdomain.com' \
  --all-tables \
  --network \
  --precise \
  --recurse-objects

#Replacing mixed protocols

If your staging site uses HTTP while production uses HTTPS (or vice versa), run two passes:

wp search-replace 'http://staging.yourdomain.com' 'https://yourdomain.com' --all-tables
wp search-replace '//staging.yourdomain.com' '//yourdomain.com' --all-tables

This catches protocol-relative URLs that some plugins and themes generate.

#Git-based deployment workflows

For teams working on custom themes or plugins, version control with git transforms the deployment process from error-prone manual copying to a repeatable, auditable workflow.

#Repository structure

A typical git-managed WordPress project tracks only the custom code, not WordPress core or third-party plugins:

.
├── .github/
│   └── workflows/
│       └── deploy.yml
├── wp-content/
│   ├── themes/
│   │   └── your-theme/
│   ├── plugins/
│   │   └── your-custom-plugin/
│   └── mu-plugins/
├── .gitignore
└── composer.json

Your .gitignore should exclude WordPress core files, uploads, cache directories, and sensitive configuration:

# WordPress core
/wp-admin/
/wp-includes/
/wp-*.php
/index.php
/xmlrpc.php

# Configuration
wp-config.php
.htaccess

# Uploads and cache
wp-content/uploads/
wp-content/cache/
wp-content/upgrade/

# Dependencies
vendor/
node_modules/

#Branch strategy

A simple branch strategy for WordPress projects:

  • main - production-ready code, deployed to the live site.
  • staging - integration branch, deployed to the staging environment.
  • feature/* - individual feature branches created from staging.

Developers create feature branches, test locally, open pull requests to staging, and after approval, the staging branch is merged into main for production deployment.

#Deploying with git on the server

If your server supports git, you can pull changes directly:

# On the production server
cd /var/www/html
git fetch origin
git checkout main
git pull origin main

# Run composer if needed
composer install --no-dev --optimize-autoloader

# Flush caches
wp cache flush
wp rewrite flush

For servers without git access, use rsync from your local machine after checking out the branch you want to deploy:

git checkout main
rsync -avz --delete \
  --exclude='.git/' \
  --exclude='node_modules/' \
  --exclude='.env' \
  ./wp-content/ \
  production:/var/www/html/wp-content/

#CI/CD basics for WordPress with GitHub Actions

Continuous Integration and Continuous Deployment (CI/CD) automates the entire workflow: when you push code to a specific branch, a pipeline runs tests, checks code quality, and deploys to the target environment automatically.

#GitHub Actions workflow example

Create .github/workflows/deploy.yml in your repository:

name: Deploy WordPress

on:
  push:
    branches:
      - main
      - staging

jobs:
  lint-and-test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.3'
          tools: composer, cs2pr

      - name: Install dependencies
        run: composer install --prefer-dist --no-progress

      - name: Run PHP CodeSniffer
        run: vendor/bin/phpcs --standard=WordPress wp-content/themes/your-theme/ wp-content/plugins/your-custom-plugin/

      - name: Run PHPStan
        run: vendor/bin/phpstan analyse wp-content/themes/your-theme/ wp-content/plugins/your-custom-plugin/ --level=6

  deploy-staging:
    needs: lint-and-test
    if: github.ref == 'refs/heads/staging'
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Deploy to staging
        uses: burnett01/rsync-deployments@7.0.1
        with:
          switches: -avz --delete --exclude='.git/' --exclude='node_modules/'
          path: wp-content/
          remote_path: /var/www/staging/wp-content/
          remote_host: ${{ secrets.STAGING_HOST }}
          remote_user: ${{ secrets.STAGING_USER }}
          remote_key: ${{ secrets.SSH_PRIVATE_KEY }}

      - name: Flush staging caches
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.STAGING_HOST }}
          username: ${{ secrets.STAGING_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /var/www/staging
            wp cache flush
            wp rewrite flush

  deploy-production:
    needs: lint-and-test
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Deploy to production
        uses: burnett01/rsync-deployments@7.0.1
        with:
          switches: -avz --delete --exclude='.git/' --exclude='node_modules/'
          path: wp-content/
          remote_path: /var/www/html/wp-content/
          remote_host: ${{ secrets.PRODUCTION_HOST }}
          remote_user: ${{ secrets.PRODUCTION_USER }}
          remote_key: ${{ secrets.SSH_PRIVATE_KEY }}

      - name: Flush production caches
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.PRODUCTION_HOST }}
          username: ${{ secrets.PRODUCTION_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /var/www/html
            wp cache flush
            wp rewrite flush

#What this pipeline does

  1. Lint and test - every push triggers PHP CodeSniffer (for WordPress coding standards) and PHPStan (for static analysis). If either fails, the deployment is blocked.
  2. Deploy to staging - pushes to the staging branch automatically deploy to the staging server via rsync over SSH.
  3. Deploy to production - pushes to main deploy to production. The environment: production setting enables GitHub’s environment protection rules, so you can require manual approval before production deploys.

#Setting up secrets

Store your SSH credentials as GitHub repository secrets:

  • STAGING_HOST and PRODUCTION_HOST - server IP addresses or hostnames.
  • STAGING_USER and PRODUCTION_USER - SSH usernames.
  • SSH_PRIVATE_KEY - the private key for SSH authentication.

Never commit private keys or credentials to your repository.

#Preventing staging from being indexed

A staging site that gets indexed by search engines creates duplicate content problems and can leak unfinished work to the public. Multiple layers of protection ensure this does not happen.

#robots.txt

Create a robots.txt file on the staging site that blocks all crawlers:

User-agent: *
Disallow: /

This tells well-behaved crawlers not to index any page. But not all bots respect robots.txt, so additional measures are necessary.

#WordPress reading settings

In the staging site’s admin, navigate to Settings, then Reading, and check “Discourage search engines from indexing this site.” This adds a noindex meta tag and an X-Robots-Tag: noindex header to every page.

#HTTP header via .htaccess or nginx

Add a server-level noindex header for extra protection. For Apache:

# .htaccess on staging
Header set X-Robots-Tag "noindex, nofollow, nosnippet"

For Nginx:

# In the staging server block
add_header X-Robots-Tag "noindex, nofollow, nosnippet" always;

#HTTP basic authentication

The most reliable protection is restricting access entirely. Add HTTP basic authentication so that only authorized people can view the staging site:

For Apache, add to .htaccess:

AuthType Basic
AuthName "Staging Access"
AuthUserFile /path/to/.htpasswd
Require valid-user

Create the password file:

htpasswd -c /path/to/.htpasswd staging_user

For Nginx, add to the server block:

auth_basic "Staging Access";
auth_basic_user_file /etc/nginx/.htpasswd;

#IP allowlisting

For the highest level of security, restrict staging access to specific IP addresses. This is especially useful for agency teams working from known office networks or VPNs.

#Common pitfalls and how to avoid them

#Forgetting to exclude wp-config.php

The wp-config.php file contains database credentials, security salts, and environment-specific constants. Overwriting production’s config with staging’s config is one of the most common deployment mistakes. Always exclude it from rsync and never commit it to git.

#Serialized data corruption

Never use SQL-level find-and-replace (e.g., UPDATE wp_options SET option_value = REPLACE(...)) for URL changes. WordPress stores serialized PHP arrays in the database, and changing string lengths without updating the serialization metadata corrupts the data. Always use WP-CLI search-replace, which handles serialized data correctly.

#Stale object cache

After any deployment, flush the object cache. If you use Redis or Memcached, stale cached objects can serve old data even after the database has been updated:

wp cache flush
redis-cli FLUSHDB    # if using Redis

#Mixed content after HTTPS migration

If your staging site uses a different protocol than production, browser mixed-content warnings can break CSS and JavaScript loading. Run search-replace on protocol-relative URLs as well as full URLs to catch every reference.

#Cron conflicts

WordPress cron jobs scheduled on staging (like scheduled posts or automated emails) can fire on the staging domain. Disable wp_cron in your staging wp-config.php to prevent unintended side effects:

define('DISABLE_WP_CRON', true);

#Building a professional deployment workflow

The best deployment workflow for your project depends on its complexity:

  • Simple blogs and brochure sites - hosting-level staging is sufficient. One-click clone, test, push to live.
  • WooCommerce stores and membership sites - use WP-CLI manual staging with careful database management. Database merges need extra attention because production data changes constantly.
  • Custom themes and plugins under active development - git-based deployment with CI/CD. Code review via pull requests, automated testing, and repeatable deployments.
  • Agency managing multiple clients - standardize on a CI/CD pipeline with environment-specific configuration. One workflow template serves every client project.

Start with the simplest approach that meets your needs and evolve your workflow as your requirements grow. The goal is not complexity for its own sake, but confidence that every deployment is safe, tested, and reversible.

#Professional WordPress deployment and maintenance

Setting up a reliable staging and deployment workflow requires expertise in server administration, database management, and CI/CD tooling. At wppoland.com, we design and maintain WordPress deployment pipelines for agencies and businesses across Europe. From one-click staging setups to fully automated GitHub Actions workflows, we handle the DevOps so your team can focus on building great websites.

If you need help setting up staging environments, automating deployments, or migrating between hosting providers, our team is ready to help. Pricing for maintenance and deployment services is individual and depends on your project scope, so reach out for a tailored consultation.

Next step

Turn the article into an actual implementation

This block strengthens internal linking and gives readers the most relevant next move instead of leaving them at a dead end.

Want this implemented on your site?

If you want to convert the article into a working site improvement, redesign, or build plan, I can define the scope and implement it.

Related cluster

Explore other WordPress services and knowledge base

Strengthen your business with professional technical support in key areas of the WordPress ecosystem.

What is a WordPress staging site?
A staging site is a private clone of your live WordPress website where you can test theme updates, plugin changes, and new features without risking downtime or errors on the production site that your visitors see.
How do I push a staging site to live in WordPress?
The safest method depends on your hosting. Managed hosts offer one-click push-to-live buttons. For manual workflows, use rsync for files and mysqldump plus WP-CLI search-replace for the database, then flush all caches.
Can I develop WordPress locally and then deploy to a server?
Yes. Tools like LocalWP, DDEV, or wp-env let you build locally. You then deploy files via git or rsync and migrate the database with WP-CLI search-replace to rewrite URLs from localhost to your production domain.
How do I prevent search engines from indexing my staging site?
Add a robots.txt file that disallows all crawlers, set the WordPress reading settings to discourage search engines, add a noindex meta tag via a plugin or theme header, and ideally restrict access with HTTP basic authentication or IP allowlisting.
Is a CI/CD pipeline worth it for a WordPress site?
For sites with custom themes or plugins under version control, a CI/CD pipeline eliminates manual deployment errors, enforces code quality through automated linting and tests, and makes rollbacks trivial.

Need an FAQ tailored to your industry and market? We can build one aligned with your business goals.

Let’s discuss

Related Articles

Complete guide to installing WordPress with Docker Compose and Composer (Bedrock). Includes full docker-compose.yml, Xdebug configuration, .env setup, and deployment workflows from local to production.
development

Install WordPress with Docker and Composer: modern dev setup for 2026

Complete guide to installing WordPress with Docker Compose and Composer (Bedrock). Includes full docker-compose.yml, Xdebug configuration, .env setup, and deployment workflows from local to production.

Manual FTP uploads are a security risk. Learn how to implement professional CI/CD pipelines for WordPress using GitHub Actions and Docker in 2026.
development

CI/CD for WordPress: Automating your deployment in 2026

Manual FTP uploads are a security risk. Learn how to implement professional CI/CD pipelines for WordPress using GitHub Actions and Docker in 2026.

Still using Local by Flywheel or MAMP? Discover why Docker is the industry standard for WordPress development in 2026 and how to set it up.
development

Docker for WordPress development in 2026: Containerization made easy

Still using Local by Flywheel or MAMP? Discover why Docker is the industry standard for WordPress development in 2026 and how to set it up.