LifterLMS Staging Site: Test Safely Without Double-Charging

How LifterLMS detects a staging copy and pauses recurring payments, what the site URL lock is, the wp-config constants that make staging safe by default, and a deployment workflow that never puts live orders at risk.

  • Add as a preferred source on Google
Illustration for “LifterLMS Staging Site: Test Safely Without Double-Charging”

Every serious LifterLMS site should have a staging copy for testing updates and new features. But a copy of a membership site is also a copy of every active subscription, every scheduled renewal and, often, the live payment gateway keys. Left alone, that copy could try to bill your students a second time.

LifterLMS has a built-in safeguard for this. This guide explains how the LifterLMS staging site detection and URL lock work, how to make staging safe by default with two lines in wp-config.php, what else to switch off on the copy, and how to deploy changes without overwriting live orders. It is for developers and site owners who run subscriptions or payment plans, and it was checked against the LifterLMS 10.3 source.

Why a staging copy can charge real customers

A LifterLMS recurring payment is a scheduled task. When an order's next payment date arrives, the scheduler runs, LifterLMS asks the payment gateway add-on to charge the saved payment method, and a transaction is recorded.

A typical staging copy is a clone of the live database. It contains the same orders, the same scheduled renewal tasks in the Action Scheduler tables, and the same gateway settings. If the clone ran those renewals with live API keys, the customer would be charged once by the live site and once by staging. Refunds and apologies follow.

How LifterLMS detects a clone: the URL lock

When LifterLMS is installed, it stores your site's URL in the llms_site_url option with a marker, _[llms_site_url]_, inserted into the middle of it. The marker exists so that migration and search-replace tools, which rewrite every copy of the old domain, do not recognise and update this value.

On every check, LifterLMS removes the marker and compares the stored URL with the site's current URL. If they differ, the site is treated as a clone. From that moment:

  • Automatic recurring payments are treated as disabled, even before anyone logs in to the admin. LifterLMS 10.3 tightened this so renewals are blocked as soon as the URL no longer matches the stored lock.
  • When an administrator opens the dashboard, a notice appears: "It looks like you may have installed LifterLMS on a staging site!", with the buttons Leave Automatic Payments Disabled and Enable Automatic Payments.
  • The Orders menu shows a Staging label while recurring payments are off.

When a renewal falls due on a site in this state, it is skipped and the order gets a note: "Recurring charge skipped because recurring payments are disabled in staging mode." Upcoming payment reminder notifications are suppressed too. You can confirm the current state under LifterLMS > Settings > General, where the Features section reads Automatic Recurring Payments: Enabled or Disabled.

The LifterLMS staging documentation describes the same notice and recommends gateway test mode and disabling email on staging, both covered below.

Make staging safe by default with wp-config constants

Relying on URL detection alone has two weak spots: a staging copy that uses the same domain (some hosts swap environments behind one URL), and someone clicking the wrong button in the notice. Remove both risks by declaring the site a clone in its wp-config.php:

// Staging and development copies only. Never on production.
define( 'LLMS_SITE_IS_CLONE', true );
define( 'WP_ENVIRONMENT_TYPE', 'staging' );

LLMS_SITE_IS_CLONE set to true makes LifterLMS treat the site as a clone whatever its URL, and forces automatic recurring payments off. With the constant defined, the staging notice and the reset tool are no longer offered, so nobody can switch payments back on from the dashboard.

WP_ENVIRONMENT_TYPE is a WordPress core setting, read through wp_get_environment_type(). LifterLMS does not use it for payments, but many other plugins, hosts and email tools do, so it is worth setting.

LifterLMS also reads LLMS_SITE_FEATURE_RECURRING_PAYMENTS, which forces recurring payments on or off directly. Avoid setting it to true on production: if wp-config.php is ever copied to a clone, the safeguard goes with it. Keep the explicit constant on the non-production side.

What else to switch off on staging

Recurring charges are the most expensive mistake, but not the only one. A cloned site will happily email students, call your CRM and accept payments.

  1. Payment gateways in test mode. Switch each gateway add-on to test or sandbox mode and use test keys, for example from Stripe's testing documentation. Then a manual checkout on staging cannot take real money either. See our LifterLMS Stripe guide.
  2. Outgoing email. Engagement emails, notifications and reminders go to real addresses. Use a mail-catching plugin or your host's option to block or trap email on staging.
  3. Webhooks and integrations. Disable LifterLMS webhooks or point them at a test endpoint, and disconnect CRM, email marketing and automation integrations, or connect them to test accounts. A staging enrollment should not tag a real contact.
  4. Search engines and visitors. Discourage indexing and put the site behind a password.
  5. Scheduled tasks. Look at LifterLMS > Status > Scheduled Actions after cloning. Past-due tasks will run on the clone's first busy minute.

Updating and deploying safely

The golden rule: move code and configuration from staging to live, never the database. While you were testing, the live site took new orders, renewals, enrollments, quiz attempts and progress. Pushing the staging database over live deletes all of that.

There is a second, quieter problem. The staging database holds staging's URL lock, or none at all. Push it to production and LifterLMS on the live site may decide it is now the clone, and renewals stop without anyone noticing until revenue drops.

A workflow that works

  1. Refresh staging from a fresh copy of live, so you test against real data and current versions.
  2. Confirm the staging notice appeared or the constant is set, and that the Features section shows recurring payments disabled.
  3. Apply updates or develop the change on staging. Test checkout in test mode, a renewal, a lesson completion and any custom code.
  4. Deploy code (plugins, theme, custom plugin) to live through version control or a file deployment.
  5. Repeat configuration changes on live by hand, or export and import courses with the course exporter. See LifterLMS import, export and cloning.
  6. On live, check Automatic Recurring Payments: Enabled and that renewals scheduled for the next few days are present.

If you truly must merge database changes, do it during a maintenance window with the live site closed to purchases, and exclude orders, transactions, user data and the scheduler tables. That is a job to plan carefully, not to improvise.

Moving production to a new domain or host

The same detection fires when the real site changes address, for example after a rebrand or a move from a temporary domain. LifterLMS cannot tell a new production domain from a staging copy, so it pauses renewals and shows the notice.

  1. Complete the move and test the site.
  2. Make sure the old site is shut down or set as a clone, so two copies never run renewals.
  3. Click Enable Automatic Payments on the new production site. This stores a new URL lock.
  4. Check Scheduled Actions for renewals that were skipped during the move, and the orders they belong to. The LifterLMS documentation warns that switching staging mode on a live site can lead to missed or catch-up payments, so review the affected orders rather than assuming everything sorted itself out.

If you clicked the wrong button, go to LifterLMS > Status > Tools & Utilities and run Reset Automatic Payments Status. It clears the stored lock and runs the check again, which brings the notice back so you can choose properly. For a larger move, our LifterLMS migration guide covers the full checklist.

Common mistakes

  • Clicking Enable Automatic Payments on staging to make a notice go away. Use the constant so the choice is not there to make.
  • Live gateway keys on staging. Even with renewals off, a test checkout would take real money.
  • Pushing the staging database to live. Orders and progress are lost, and renewals may stop.
  • Same-URL staging environments that bypass URL detection. Define LLMS_SITE_IS_CLONE.
  • Forgetting the live site after a domain change. Renewals stay paused until someone enables them.
  • Leaving webhooks active on the clone, so test enrollments land in the live CRM.

Frequently asked questions

Does LifterLMS automatically disable payments on staging?

Yes, when the staging site's URL differs from the stored URL lock, automatic recurring payments are treated as disabled. Manual checkouts still work, which is why gateways should be in test mode as well.

What happens to renewals that fall due on staging?

They are skipped and the order gets a note saying the recurring charge was skipped because recurring payments are disabled in staging mode. The live site's copy of the order is unaffected.

How do I know if recurring payments are on?

Look at the Features section under LifterLMS > Settings > General, which shows Automatic Recurring Payments as Enabled or Disabled. A Staging label on the Orders menu also means they are off.

Do I need the wp-config constant if detection works?

It is not required, but it removes the risk of a same-domain staging setup or a wrong click. It is a two-line change worth making on every non-production copy.

What to do next

Add LLMS_SITE_IS_CLONE to your staging wp-config.php today, switch its gateways to test mode and trap its email. Then write down your deployment steps so the next update follows them.

If you want a proper development workflow with version control, automated deployments and a staging environment that refreshes safely, our LifterLMS development team sets these up, and our support plans handle updates for you. Tell us how your site is hosted and we will suggest a setup.

Add LifterLMS Expert to your preferred sources

Add lifterlmsexpert as a preferred source on Google, or open this article in your AI assistant to use it as a source.

  • Add as a preferred source on Google
VishavjeetChoubeyLifterLMS Expert
Free consultation

Prefer expert help over DIY?

Skip the trial and error. Get specialist LifterLMS help and ship faster.

Talk to a LifterLMS Expert Explore our services

Replies within one business day