Normal view

There are new articles available, click to refresh the page.
Before yesterdayMain stream

Automating Database Syncs with WP Migrate and WP-CLI

11 May 2026 at 19:45

Modern development workflows have mostly solved the file problem. We use Git to version our themes and plugins, and we use CI/CD pipelines to deploy those files to staging and production. But for many teams, the database remains a manual, high-stakes bottleneck.

Whether you are pulling production data down to a local environment for debugging or pushing a new ACF field structure up to staging, relying on manual SQL exports and imports is a recipe for disaster. It’s slow, it’s prone to human error, and it’s the most common way to break serialized data.

To reach true deployment maturity, you need to automate the database layer. That’s where WP Migrate’s integration with WP-CLI comes in.

Why wp db export Isn’t Enough

Many developers start by using the native wp db export and wp db import commands. While these are great for simple backups, they are dangerous for migrations between environments.

The primary culprit is serialized data. WordPress often stores complex data (like widget settings or ACF configurations) as serialized PHP objects. If your search-and-replace changes the length of a string (e.g., changing http://localhost to https://production.com), a standard SQL find-and-replace will break the serialization, and the data will simply vanish from the frontend.

Unlike standard SQL exports that treat the database like a flat text file, WP Migrate’s background logic handles search-and-replace at the PHP level. When the migration runs, the plugin identifies serialized data and temporarily unserializes it to perform the string replacement on the actual data structure. Once the strings are updated, it re-serializes the data and automatically recalculates the internal string-length counts before committing it to the destination database. This process ensures your metadata remains intact even when the new site URL has a completely different character count than the old one.

The Bridge: Migration Profiles

You can start firing off commands in the terminal at this point, but it’s probably better to create a Migration Profile first. Migration Profiles are a specialized feature provided by WP Migrate to manage complex configurations.

Migration Profiles are basically saved presets for your migration. In the WP Migrate UI, you define:

  • Which tables to include or exclude.
  • Specific find-and-replace pairs.
  • Whether to sync the Media Library or theme files.

By defining these in the UI first, you avoid the headache of passing dozens of complex arguments into a terminal command. Once saved, the CLI can trigger the entire logic of that profile using a single ID.

Selective Table Syncing: Protecting Production

The most significant risk in database automation is the push operation, when you move data from a lower environment (like Local or Staging) to the live Production server. If you push a full database that you’ve been working on for several days, you will overwrite the live site with your outdated local data, potentially wiping out every eCommerceorder or user registration that happened while you were developing.

This is where selective syncing becomes a mandatory safety measure. Instead of an “all or nothing” approach, WP Migrate’s integration with WP-CLI allows you to be surgical. In your Migration Profile, you should configure specific exclusions for transactional tables:

  • wp_users and wp_usermeta
  • wp_comments
  • wp_posts and wp_postmeta (specifically if you only want to sync settings/structures, not content)

By excluding these, you can perform a structural push that sends new ACF field groups or plugin configurations to production without the nightmare scenario of deleting customer data.

The Workflow: Push vs. Pull

In a professional pipeline, the direction of your migration depends on your goal.

Direction Command Best For… Risk Level
Pull wp migrate pull <ID> Refreshing staging with fresh production data. Low (Overwrites local/staging)
Push wp migrate push <ID> Deploying new ACF structures or settings to staging. High (Overwrites remote)

Automating with Secret Keys

WP Migrate uses secret keys for authorization. This means you don’t need to manage complex SSH tunnels just to move data. When setting up your CI/CD pipeline (like GitHub Actions), you should store these credentials as environment-scoped secrets within your CI/CD provider (like GitHub Actions or GitLab CI).

By scoping secrets specifically to the Production environment, you can implement protection rules, such as requiring a manual approval before the secrets are injected into a workflow. This ensures that a database push to your live site only happens when a senior team member has signed off on the deployment.

Real-World Implementation: GitHub Actions Snippet

Here’s how you might automate a Pull request to refresh a Staging site with Production data whenever a new release is tagged.

jobs:
  db-refresh:
    runs-on: ubuntu-latest
    steps:
      - name: Trigger WP Migrate Pull via SSH
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.STAGING_HOST }}
          username: ${{ secrets.STAGING_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            # Navigate to the site root and trigger the saved profile
            cd /var/www/html
            wp migrate pull 5 --path=/var/www/html

In this example, the number 5 represents the specific ID of a Migration Profile created in the WP Migrate UI. Once you’ve identified your ID via the wp migrate profiles list command, the CLI takes it from there, automatically executing the authentication, the PHP-level search-and-replace, and the table exclusions you’ve already defined. This keeps your deployment script clean, as the heavy lifting of the configuration stays within the profile itself.

Conclusion

Manual migrations are basically technical debt. They eat up developer time and introduce unnecessary risk into your deployment cycle. By leveraging WP Migrate’s integration with WP-CLI, you move the database out of the manual task column and into your automated pipeline.

Whether you are syncing data for QA or deploying complex structural changes, using Migration Profiles and WP-CLI ensures that your environments stay in parity and your serialized data stays safe.

The post Automating Database Syncs with WP Migrate and WP-CLI appeared first on Delicious Brains.

Debugging WP-Cron With WP-CLI

3 February 2026 at 20:17

It’s a common situation. You schedule a backup for 2 a.m., but when you log in the next morning, the file isn’t there. Or perhaps a scheduled post missed its publication window, leaving you with a “Missed Schedule” error.

The root cause is often the WordPress cron system. Unlike a standard system cron that runs on a strict clock, WP-Cron is a pseudo-cron. It relies on page visits to trigger scheduled tasks. If no one visits the site, the tasks don’t run. If a visitor arrives while a heavy task is pending, their page load might hang while WordPress processes the queue in the background.

Debugging this via the WordPress dashboard is often frustrating. Installing a plugin just to view your cron events adds unnecessary bloat. A more direct and reliable method is to use the command line.

WP-CLI provides immediate visibility into the scheduler and, more importantly, allows you to force-run events to see if they fail.

Gaining Visibility

The first step in debugging is seeing what is actually in the queue. The default dashboard gives you no insight into this, but one command reveals the entire schedule.

Run the following command in your terminal:

wp cron event list

This outputs a table with four key columns: hook, next_run_gmt, next_run_relative, and recurrence.

The most important column for debugging is next_run_relative.

  • If it says “10 minutes” or “1 hour,” the event is scheduled for the future.
  • If it says “now”, “1 hour ago”, or “Yesterday”, the event is stuck.

A “stuck” event usually means one of two things: either the site hasn’t had any traffic to trigger the runner, or the PHP script attempted to run but crashed silently.

The Magic Fix: Force Running Events

Waiting for a suspect task to run naturally is inefficient. You need to see the error output immediately.

You can force any event to run right now, regardless of its schedule, using the run command:

wp cron event run <hook_name>

For example, if your backup hook is named my_daily_backup, you would run:

wp cron event run my_daily_backup

When WP-Cron runs normally (via a page visit), PHP errors are often suppressed or hidden in a log file you might not be checking. Fatal errors are output directly to your terminal when you run it via WP-CLI.

If the script is running out of memory or hitting a PHP timeout, the command line will tell you instantly.

Clearing the Backlog

If you manage a site that has been offline or neglected, you might find dozens of overdue tasks clogging the queue. Rather than running them one by one, you can force WordPress to process all overdue events at once:

wp cron event run --due-now

Cleaning Up the Junk

Over time, the wp_options table can accumulate orphaned cron events. These are scheduled tasks left behind by plugins that were deactivated or deleted incorrectly. They don’t break the site, but they do clutter the database and the cron list.

To delete a specific event:

wp cron event delete <hook_name>

Be careful not to delete core WordPress hooks (like wp_scheduled_delete or wp_version_check). Focus only on hooks clearly named after plugins you no longer use.

Alternative: Disabling the Default WP-Cron

For high-traffic sites, or sites where timing is critical, relying on page visits to trigger tasks is often insufficient. In these cases, it’s common to disable the default behavior and replace it with a system cron.

This involves two steps. First, you disable the trigger in wp-config.php:

define('DISABLE_WP_CRON', true);


This stops WordPress from checking for scheduled tasks on every page load, which can improve page load speed for users.

However, once this is disabled, nothing will run until you set up an alternative trigger. You must add an entry to your server’s system crontab to call WP-CLI every minute.

Important: Do not run this as the root user. WP-CLI limits root execution for security reasons. Instead, add this line to the crontab of your web server user (often www-data) or your specific hosting user:

* * * * * /usr/local/bin/wp cron event run --due-now --path=/var/www/yoursite/ > /dev/null 2>&1


There are three key changes in this command compared to a standard manual run:

  1. Full Path: We use /usr/local/bin/wp because system crons run in a minimal environment and might not know where the wp command is located otherwise.
  2. Path to Site: The --path flag ensures WP-CLI executes within the correct WordPress installation.
  3. Silencing Output: The > /dev/null 2>&1 at the end prevents the server from emailing you a notification every single minute that the task ran successfully.

This configuration ensures that scheduled tasks run precisely on time, regardless of whether anyone is visiting the website.

Conclusion

WP-Cron shouldn’t be viewed as a “black box” that developers cross their fingers and hope works. Shifting your workflow to the terminal turns that black box into a transparent queue. Using wp cron event list and run allows you to diagnose issues in seconds rather than days, ensuring your backups, emails, and scheduled posts happen exactly when they are supposed to.

The post Debugging WP-Cron With WP-CLI appeared first on Delicious Brains.

❌
❌