Should you test lifecycle emails in sandbox before connecting live billing?

You can spend time polishing a lifecycle email, send yourself a test, and still miss the part that breaks in real use.
The email may render well. The button may work. But the billing event behind it may not reach your system, may carry different data than you expected, or may change a subscription without sending the signal you built around.
If your store, app, or workflow sends emails after billing changes, test the whole path before connecting live billing.
That means more than sending a preview. It means choosing a plan, approving it, returning from Shopify, checking what your system records, and seeing which email sends at each point.
A preview checks the template, not the lifecycle
In Shopify admin, go to Settings → Notifications. You can preview a notification or use Send test email. The test goes to the email address you use to log in to Shopify admin.
Do this. It catches simple problems fast:
- A logo that is too wide on mobile
- A missing product title
- A link pointing to the wrong place
- Text that sounds wrong once it arrives in an inbox
But a preview is not a billing test. It does not prove that a plan change will trigger the right message. It also does not prove your app or workflow receives and stores the right subscription state.
The same distinction applies to webhooks. Shopify's CLI can send a synthetic webhook POST to your endpoint. That is useful for testing whether your code can process a payload. Shopify says it does not confirm that the webhook subscription itself is configured correctly.
Treat these as separate checks:
- Template test: does the email look and read correctly?
- Webhook test: can your endpoint process a sample event?
- Lifecycle test: does the real sequence create the right state and send the right email?
You need all three when billing is involved.
Test the complete billing path in a development store
Shopify's current guidance for Shopify App Pricing is to test the full billing flow in a development store before enabling live pricing.
That test should cover more than initial approval. Walk through:
- Plan selection
- Merchant approval
- Redirects back to your app or service
- Displayed price and billing interval
- Trial terms, if you offer a trial
- Welcome links and post-approval screens
- Subscription status
- Usage meters, if your pricing uses them
For an app and development store in the same Shopify Partner organization, Shopify creates the subscription contract with effective recurring and usage prices of $0. You can test the approval flow without a real payment.
That makes a development store the right place to find issues that would be awkward in a live store. For example, say a merchant approves a monthly plan, but your welcome email says their trial starts today when no trial exists. A template preview would not catch that. A full billing test should.
Make a small test sheet before you start. It can be a plain document with one row for each event:
| Action | What should change | What email should send | | --- | --- | --- | | Approve a plan | Subscription becomes active | Welcome or confirmation | | Change plans | Plan and price update | Plan-change confirmation | | Schedule cancellation | Cancellation date is stored | Cancellation notice | | Cancel | Access and status update | Final confirmation |
Then fill it in as you test. You are checking what happened, not what you meant to build.
Do not build emails around old subscription-change assumptions
Billing lifecycle details matter because the source of truth can change.
For Shopify App Pricing, Shopify no longer sends subscription-change webhooks after April 28, 2026. Apps need to use Partner API queries and redirect URL parameters, such as `plan_handle`, instead.
This affects lifecycle email design. If an email depends on a customer moving from one plan to another, do not assume a subscription-change webhook will tell you about it. Confirm where your workflow gets that change now.
Shopify documents these App Pricing lifecycle event types:
- `SUBSCRIPTION_CREATED`
- `SUBSCRIPTION_UPDATED`
- `SUBSCRIPTION_CANCELLATION_SCHEDULED`
- `SUBSCRIPTION_CANCELED`
- `SUBSCRIPTION_FROZEN`
- `SUBSCRIPTION_UNFROZEN`
A practical check takes less than a minute: open the code or automation that decides whether to send a billing email. Find the event or status it relies on. If it expects a webhook that Shopify no longer sends for App Pricing changes, stop there and fix the source before working on copy.
When you query lifecycle events through the Partner API, remember the limits. It returns the last 30 days by default, supports a maximum range of 365 days, and limits pages to 250 events. If you are reconciling a backlog or building a daily check, handle pagination rather than assuming one response is the whole history.
We learned the same lesson while building our own tooling. Shopify's `/products.json` returns at most 250 products per page. A catalogue read can look complete while quietly missing products. Billing events are different data, but the testing habit is the same: check where a list stops, and make sure your code asks for the next page.
Use the right test for the email you send
Not every lifecycle email is tied to app billing.
For order-triggered messages, place at least one test order. Shopify recommends this because a test order can validate order processing, inventory, shipping, email notifications, and taxes. Shopify's Test payment gateway and Shopify Payments test mode do not charge the merchant. Test orders do not appear in payouts or reports.
For subscription emails sent to shoppers, check whether the template has the data it needs. Shopify's subscription email templates can use the `subscription_contract_billing_cycle` object, including the subscription contract, current billing cycle, line items, delivery method, and payment method. Shopify says those templates require the Shopify Subscriptions app.
Test with a scenario that has real values for the fields your email shows. An empty sample is not enough if your live message needs a renewal date, a delivery method, or a payment method.
Keep sandbox and live settings clearly separate
A sandbox test only helps if it cannot quietly become a live charge.
We followed this approach before wiring real invoicing in our own product. We chose an API key restricted to only what the feature needed, then tested every flow in sandbox before touching live mode. The point was not ceremony. It gave us room to see the actual requests, responses, and failure cases without creating a real billing problem.
If you use Shopify's manual Billing API pricing rather than Shopify App Pricing, there is a separate switch to check. Create test charges with the Billing API `test` field set to `true`. After testing, set it to `false`. If you leave it enabled, installed merchants will not be charged.
Put that check in your release list. It is easy to overlook because both mistakes are quiet: live billing during testing is bad, but so is a live launch that never charges anyone.
A short release check
Before you connect live billing, verify these points:
- The notification renders correctly in Shopify's test email.
- A development-store billing flow reaches approval and returns correctly.
- Your system records the expected plan, status, price, interval, and trial details.
- Each billing state has one clear email rule, including cancellation and frozen states where relevant.
- The workflow reads subscription changes from Shopify's current supported source.
- Any event query handles more than one page of results.
- Test billing settings cannot remain enabled by accident in production.
- A test order has covered order-triggered messages separately from app billing.
Start with one complete sandbox path: approve a plan, inspect the recorded status, and read the email that follows. That single run will tell you far more than a template preview alone.