Table of Contents
- Key Highlights:
- Introduction
- What Shopify is changing and which apps are affected
- What is an offline access token and how does it differ when it expires
- Why expiring tokens substantially reduce risk
- Implementing expiring offline access tokens: practical guidance
- Token storage and security best practices
- Handling webhooks, background jobs, and scheduled tasks
- Error handling, retries, and merchant reauthorization
- Migration and compatibility: what developers need to know
- Real-world examples and patterns
- Common pitfalls and how to avoid them
- Using Shopify’s templates and libraries
- Operational checklists for launch and scale
- Developer experience and merchant communication
- Monitoring and incident response
- Third-party integrations and OAuth complexity
- Preparing for future changes
- Community and support resources
- FAQ
Key Highlights:
- Beginning April 1, 2026, all newly created public Shopify apps must request and use expiring offline access tokens to reduce long-term exposure if credentials leak.
- Existing public apps created before this date remain unaffected; custom apps and merchant-created apps are exempt. Shopify app templates and official libraries already support the new flow.
- Developers must implement a refresh flow, handle token rotation reliably for background jobs and webhooks, and follow secure storage and monitoring practices to protect merchant data.
Introduction
Shopify is changing how public apps authenticate when they need long-lived access to merchant stores. Historically, many apps obtained non-expiring offline access tokens that granted persistent access to a merchant’s store without repeated reauthorization. Those tokens simplified background processing, but they created a persistent security surface: if a token leaked, it could be used indefinitely.
On April 1, 2026, Shopify will require all new public apps to use expiring offline access tokens. The move aligns Shopify with modern OAuth patterns and reduces the window of opportunity for misuse when credentials are compromised. For developers, the change shifts some complexity from perpetual tokens to reliable refresh flows and robust token management—but it sharply reduces risk for merchants and app developers alike.
This article explains what’s changing, who must act, the technical differences between expiring and non-expiring tokens, detailed implementation guidance, operational patterns for background processing, migration considerations, and common pitfalls. Real-world examples show how to adapt background workers, webhooks, and integrations while preserving availability for merchants.
What Shopify is changing and which apps are affected
Shopify is requiring new public apps to request and use expiring offline access tokens. The effective date is April 1, 2026. This requirement affects only public apps created after that date. The following categories are not affected:
- Public apps created before April 1, 2026: these retain their existing behavior.
- Custom apps: apps built for a single merchant remain exempt.
- Apps created by merchants through the Dev Dashboard or admin interface: these remain unaffected.
Shopify’s decision aims to protect merchant data and align with modern OAuth practices. Developers building new public apps must implement a refresh token flow that can obtain new offline tokens when old ones expire. Shopify’s official app templates and SDKs already implement the expiring-token flow, so developers starting from those resources will have much of the logic handled for them.
What is an offline access token and how does it differ when it expires
Offline access tokens provide an app with the ability to access a merchant’s store outside a browser session, enabling background jobs, scheduled syncs, and other asynchronous processes. Traditionally, "offline" implied persistence: a token that did not expire until revoked. Shopify’s shift introduces expirations for offline tokens while preserving the offline use-case: apps can still perform background work, but tokens will have a finite lifetime and must be refreshed.
Key differences:
- Lifetime: Non-expiring tokens remain valid until revoked. Expiring tokens have a finite lifespan (for example, hours or days) and require periodic refresh.
- Refresh flow: With expiring tokens, the app must exchange a valid refresh token or perform an OAuth refresh step to get a new access token. Non-expiring tokens required no refresh.
- Risk window: Expiring tokens limit the time an attacker can use a leaked token. Shorter lifespans reduce exposure.
- Predictability: Expiring tokens force apps to incorporate token lifecycle logic, making behavior more explicit and testable.
Expiring offline tokens combine the operational convenience of offline access with the security advantages of rotation and revocation.
Why expiring tokens substantially reduce risk
Limiting the lifetime of credentials reduces the blast radius when a secret escapes controls. Consider these scenarios:
- A developer’s laptop with stored credentials is stolen. With a non-expiring token, an attacker gains indefinite access until the token is detected and revoked. With expiring tokens, access lapses after the token’s TTL (time-to-live), narrowing exposure and giving defenders a fixed window to detect abuse.
- A misconfigured log accidentally captures tokens. Expiring tokens limit the utility of those logs for an attacker.
- Insider threats or compromised CI pipelines leak tokens. Rotation and expiration mitigate long-term misuse, even when detection is slow.
Expiring tokens also promote better engineering practices. Teams implementing refresh flows typically add monitoring, alerting for failed refresh attempts, and fallback strategies for token renewal. Those practices improve reliability as well as security.
Shopify’s change aligns with OAuth best practices used broadly across major platforms. Systems that rotate tokens and require refresh also make it easier to implement conditional access and to revoke access by revoking the refresh token itself.
Implementing expiring offline access tokens: practical guidance
The primary task for developers building new public apps is to implement a refresh flow that keeps tokens valid when needed and gracefully handles expiry when not. The following steps and patterns will help:
- Request the correct offline scope during OAuth install
- When the merchant installs the app, your OAuth request must request offline access per Shopify’s updated documentation. Using Shopify’s official libraries or templates usually handles this.
- Ensure your authorization dialog and app metadata clearly explain why offline access is needed: scheduled syncs, background jobs, webhooks, etc.
- Store tokens securely
- Encrypt tokens at rest using robust key management. Protect encryption keys separately from application code.
- Avoid storing tokens in logs or error traces. Scrub logs that may contain tokens, and ensure CI systems do not expose them.
- Apply least privilege: limit which services and accounts can read token storage.
- Implement a refresh mechanism
- Track token expiry timestamps in your database.
- Refresh proactively: schedule refresh attempts well before expiration to avoid lapses that interrupt background processing and webhooks.
- On refresh failure, implement retries with exponential backoff and alerting for persistent failures.
- Handle revoked or invalid refresh tokens
- Detect 4xx errors from OAuth endpoints that indicate revocation or invalidation. When a refresh fails for reasons indicating merchant revocation, initiate a reauthorization process that directs the merchant to re-grant permissions.
- Provide clear UI and email messaging so merchants understand why reauthorization is required.
- Support background jobs and server-to-server flows
- Design background workers to use the latest valid token. If a worker finds a token expired, it should either wait for the refresh to complete or trigger the refresh itself.
- Avoid long-running processes holding a token in memory for extended periods without checking expiry.
- Audit and monitoring
- Log token issuance, refresh events, and refresh failures separately from sensitive token values.
- Alert on high refresh failure rates, unexplained spikes in token requests, or refreshes coming from unexpected locations.
- Use Shopify libraries where possible
- Shopify’s official app templates and SDKs already handle these flows. Using them reduces the chance of misimplementation.
Below are practical examples and pseudocode illustrating these patterns.
Example: Basic token refresh pseudo-flow
This pseudocode shows a simplified approach for a server that stores access tokens with expiry and refreshes them when necessary. Replace endpoints and parameters with the values from Shopify’s documentation or SDK.
Pseudo-logic:
- On OAuth completion: store access_token, refresh_token, and expiry_time.
- For each operation: ensure token is valid; if within a safety window of expiry, refresh first.
Pseudocode:
function ensureValidToken(shopId):
tokenRecord = database.getToken(shopId)
now = currentTime()
if tokenRecord.expiryTime - now < safetyMargin:
refreshed = refreshToken(tokenRecord.refreshToken)
if refreshed.success:
database.updateToken(shopId, refreshed.accessToken, refreshed.refreshToken, refreshed.expiryTime)
return refreshed.accessToken
else:
handleRefreshFailure(shopId, refreshed.error)
return null
return tokenRecord.accessToken
function refreshToken(refreshToken):
response = http.post(OAUTH_REFRESH_ENDPOINT, {
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
grant_type: 'refresh_token',
refresh_token: refreshToken
})
if response.status == 200:
return { success: true, accessToken: response.access_token, refreshToken: response.refresh_token, expiryTime: now + response.expires_in }
else:
return { success: false, error: response.body }
Key operational decisions:
- Set safetyMargin to a useful buffer (e.g., 5–15 minutes) so background tasks do not start with a token that expires mid-run.
- Refresh tokens themselves may have lifetimes; store and rotate them as well if Shopify issues rotating refresh tokens.
Example: Background worker that processes orders nightly
A common use case for offline tokens is nightly synchronization of orders or inventory updates. The worker must guarantee a valid token before processing.
Worker pseudocode:
function nightlySync():
shops = database.getShopsWithSyncEnabled()
for shop in shops:
accessToken = ensureValidToken(shop.id)
if not accessToken:
log("Skipping shop", shop.id, "due to invalid token")
notifyOpsIfNeeded(shop.id)
continue
processOrders(shop.id, accessToken)
Design notes:
- Run ensureValidToken at the start of each shop-specific run.
- If refresh fails, do not proceed. Alert ops and notify the merchant through the admin UI or email if reauthorization is needed.
- If processing large batches per shop, consider splitting into smaller tasks that each validate token independently to limit the impact of one expired token on the whole batch.
Token storage and security best practices
Secure token storage and handling prevent many common sources of leakage.
Encryption and secrets management:
- Use a managed key management service (KMS) to encrypt tokens at rest.
- Avoid hardcoding encryption keys or client secrets in source code or configuration files stored in source control.
- Rotate encryption keys periodically and practice key rollover.
Access control:
- Limit who and what can access the token storage. Use role-based access control (RBAC) and audit access.
- Segregate environments: production tokens should not be shared in staging or development environments.
Logging hygiene:
- Ensure logs never contain full token values. Mask or redact tokens in any logs or error reports.
- Avoid printing tokens to console or to third-party logging services without redaction.
Transmission security:
- Always use TLS for communicating with Shopify and for internal services transferring tokens.
- Verify certificates and use modern TLS configurations.
Operational security:
- Implement alerts for unusual token activity—multiple refresh requests in rapid succession, refreshes from unexpected IPs, or sudden spikes in token issuance.
- Provide an admin interface to revoke tokens for any merchant when necessary and to inspect token health.
Compliance and privacy:
- Only request scopes that your app needs. The principle of least privilege reduces risk and improves merchant trust.
- Be transparent with merchants about why you request offline access and which background tasks depend on it.
Handling webhooks, background jobs, and scheduled tasks
Expiring offline tokens affect how you build integrations that run outside the context of a merchant session. Each integration type has specific considerations.
Webhooks:
- Webhooks from Shopify continue to deliver events to your endpoints independent of whether your token has expired. Webhook delivery does not require an access token.
- However, handlers that call back to Shopify’s API using an expired token will fail. Ensure webhook handlers validate token state and refresh as needed before making API calls.
- If your webhook handler cannot refresh a token, queue the event and retry after successful token refresh, or handle event replay when the merchant reauthorizes.
Scheduled tasks:
- Save the next scheduled run time for periodic jobs and ensure the token is valid before executing.
- For long-running scheduled tasks, break the workload into smaller jobs and verify token validity between each job item.
Ad-hoc API calls (on-demand syncs):
- Confirm token validity at the start of the on-demand operation and refresh if needed.
- Provide immediate feedback to merchant-facing UI if a refresh fails and reauthorization is required.
Practical pattern: central token manager
- Implement a token manager service responsible for all refresh logic. Workers and webhook handlers call this service to get a valid token.
- The token manager coordinates refresh attempts to prevent thundering herd problems when many workers detect imminent expiry simultaneously.
- Use locking or atomic compare-and-swap when rotating tokens so only one process executes the refresh and other processes wait for completion.
Example: token refresh coordination
- When a token nears expiry, attempt to acquire a short-lived lock (e.g., Redis lock) for that shop’s token.
- If the process acquires the lock, perform the refresh and update the database.
- If another process finds the lock held, wait for completion then read the updated token.
Error handling, retries, and merchant reauthorization
Token refresh endpoints can return several classes of errors. Handle each deliberately:
- Temporary network errors or 5xx responses: retry with exponential backoff. Persistent errors should trigger alerts.
- 4xx responses indicating invalid refresh token or revoked access: treat these as fatal for the current authorization. Notify the merchant and prompt for reauthorization.
- Rate limiting from Shopify: respect Retry-After headers and back off. Consider staggering refreshes to avoid spikes.
Reauthorization UX:
- Provide a clear path in your app’s admin UI for merchants to reauthorize the app. Present context: what failed, what permissions are requested, and why reauthorization is needed.
- Keep merchants informed when background syncs are interrupted due to missing authorization.
Logging and triage:
- Log refresh failures with enough context for triage—shop id, error type, response codes, timestamps—without storing token values.
- Correlate refresh failures with merchant activity and support tickets so you can rapidly respond to merchant inquiries.
Migration and compatibility: what developers need to know
Shopify’s mandate applies only to new public apps created on or after April 1, 2026. Existing public apps created before the cutoff remain on their current model. Custom apps and merchant-created apps are exempt. Despite this scope, developers should plan for the long-term:
- If you plan to publish a new public app after the effective date, build for expiring offline tokens from the start.
- If you operate an SDK or framework used by others, update libraries so new apps use the expiring-token flow by default.
- Consider migration for older apps voluntarily. Moving an established app to expiring tokens reduces risk but requires careful planning.
Migration considerations for existing public apps:
- Inventory where tokens are used: background jobs, third-party integrations, scheduled exports, and worker instances.
- Build the refresh flow and the token manager in parallel with existing token usage. Test thoroughly in staging with merchant test stores.
- Coordinate merchant communication: if you plan to rotate tokens that could interrupt service, warn merchants and provide a reauthorization path.
- Handle the coexistence of non-expiring and expiring tokens in your storage layer. Mark tokens with metadata indicating type and expiry.
Why migrate voluntarily?
- Security posture improves.
- Better alignment with modern OAuth practices reduces future engineering debt.
- Preparedness for possible future Shopify changes that might extend mandatory requirements to older apps.
Real-world examples and patterns
Example 1: Inventory synchronization app
- Use case: an app synchronizes inventory across warehouses nightly and adjusts quantities based on external ERP data.
- Pattern: a central scheduler enumerates shops, calls the token manager for a valid token, and dispatches worker tasks that process SKU batches. Each worker revalidates the token for its batch and triggers a refresh if necessary.
- Failure mode handling: if token refresh fails for a shop, the app pauses synchronization for that shop and notifies the merchant with instructions to reauthorize.
Example 2: Bulk order export tool
- Use case: an app performs a weekly export of all orders for analytics.
- Pattern: export job begins by securing a valid token with a wider safety margin before initiating streaming operations. If the export takes hours, the job periodically checks remaining token lifetime and refreshes if a refresh token is available.
- Optimization: split exports into per-day or per-shop tasks to reduce the likelihood of a mid-run token expiry.
Example 3: Embedded admin app with background workers
- Use case: embedded app provides merchant-facing interfaces for configuration and also runs background reconciliation tasks.
- Pattern: the embedded UI uses short-lived session tokens for UI calls; the background service uses expiring offline tokens with refresh. Both flows are coordinated through the same token manager to avoid duplicate refresh logic.
Common pitfalls and how to avoid them
Pitfall: Expecting non-expiring behavior for background jobs
- Avoid assuming a token remains valid indefinitely. Implement checks before any long-running request.
Pitfall: Not coordinating refresh attempts
- Without coordination, many workers can attempt refresh simultaneously, causing rate limits or token inconsistency. Use locks or a central service to serialize refreshes per shop.
Pitfall: Poor alerting on refresh failures
- Background failures can go unnoticed without proper monitoring. Alert when refresh attempts fail repeatedly or when a merchant’s tokens are revoked.
Pitfall: Storing tokens insecurely
- Leaked tokens remain a top risk. Encrypt them, limit access, and scrub logs.
Pitfall: Over-requesting scopes
- Request only required scopes to reduce merchant reluctance and limit potential misuse.
Pitfall: Failing to handle revoked refresh tokens
- If a refresh token is revoked, your app must prompt the merchant to reauthorize. Build a smooth reauthorization UX with clear steps.
Pitfall: Ignoring webhook interplay
- Webhooks do not require valid access tokens for Shopify to deliver events. Ensure webhook handlers can gracefully handle missing or expired tokens when they need to make API calls.
Using Shopify’s templates and libraries
Shopify states that their app templates and libraries already implement support for expiring offline access tokens. Use these resources to accelerate development and reduce the chance of errors:
- Official app templates include OAuth flows and refresh logic configured to the recommended behavior.
- SDKs typically encapsulate token storage, expiry tracking, and refresh mechanics.
- Community examples and the Shopify developer forums provide practical patterns and troubleshooting tips.
When using third-party libraries, validate their token handling and ensure they implement secure storage, refresh coordination, and error handling consistent with the practices described above.
Operational checklists for launch and scale
Pre-launch checklist for a new public app:
- Confirm OAuth request includes offline scope per Shopify’s updated docs.
- Build and test refresh logic with realistic expiry windows.
- Securely store tokens with encryption and KMS.
- Implement a central token manager service and coordinate refresh attempts.
- Add robust logging and alerting for refresh failures and token abnormality.
- Create merchant-facing reauthorization flows and helpful error messages.
- Load-test refresh endpoints and background workers to observe behavior under scale.
Scaling checklist:
- Implement sharding or batching for large numbers of shops to avoid spiking refresh requests near midnight or other common windows.
- Use distributed locks for refresh coordination (e.g., Redis locks).
- Monitor global refresh rates and watch for correlated failures.
- Maintain a pattern for graceful degradation: skip shops with invalid tokens and notify merchants rather than blocking operations for all shops.
- Regularly rotate client secrets and encryption keys per organizational security policies.
Developer experience and merchant communication
Developer experience:
- Developers will need to implement more OAuth lifecycle logic up front, but this yields clearer, testable behavior and fewer long-term surprises.
- Use existing libraries and templates to reduce integration time.
- Document token lifecycle behavior in your developer and operations guides so on-call engineers can respond to issues.
Merchant communication:
- Be transparent about why the app needs offline access. Short, clear explanations reduce merchant friction.
- Provide a simple one-click reauthorization path in the app.
- When a reauthorization is required, explain consequences: what features will be paused and how to restore full functionality.
Example merchant messaging:
- “To continue nightly order syncing, please reauthorize {App Name}. This allows the app to securely refresh access and run scheduled tasks without requiring you to log in each time.”
Monitoring and incident response
Essential metrics to monitor:
- Refresh success rate by shop and across the fleet.
- Time-to-refresh (latency of the refresh endpoint).
- Number of shops requiring reauthorization.
- Unusual patterns: repeated refresh attempts for a single shop, many revocations in a cluster.
Incident response playbook:
- Triage: identify whether errors are transient (network, rate limit) or permanent (revoked permissions).
- Communicate: notify affected merchants proactively with clear remediation steps.
- Remediate: if a system bug causes refresh failures, deploy a fix then re-trigger refresh attempts for impacted shops.
- Post-mortem: analyze root causes, update runbooks, and add alerts to prevent recurrence.
Third-party integrations and OAuth complexity
Many apps integrate with external services in addition to Shopify. Each integration may have its own token lifecycles and security models. Keep these principles:
- Treat every external credential with equal care. The weakest link in the chain often determines overall security posture.
- Centralize credential storage and lifecycle management where practical so your team operates a single runway for rotation and revocation.
- Where possible, use short-lived credentials for all integrations and build refresh patterns consistently.
Cross-service orchestration:
- If a background job needs access to multiple services, ensure each credential is valid before starting the task.
- Build idempotent job designs so tasks can be retried safely if a credential refresh is required mid-run.
Preparing for future changes
Shopify’s policy change for new public apps signals a direction toward stronger token lifecycle controls. Developers should adopt practices that will ease future transitions:
- Build token lifecycle management from day one.
- Keep OAuth code modular so changes in grant types or refresh mechanics require minimal rework.
- Stay connected to Shopify’s developer communications and the developer community to anticipate further API and policy changes.
Community and support resources
Shopify recommends engaging with the dev platform community for help. The community channels provide:
- Peer troubleshooting for edge cases and migration patterns.
- Shared libraries and utilities that encapsulate refresh logic, token managers, and secure storage examples.
- Announcements about SDK updates, security advisories, and changes to OAuth behavior.
When escalating issues to Shopify support, provide clear logs (without tokens), timestamps, and request/response details to speed diagnosis.
FAQ
Q: Which apps must implement expiring offline access tokens? A: All new public apps created on or after April 1, 2026 must request and use expiring offline access tokens. Public apps created before that date are not required to change. Custom apps and apps created by merchants through the Dev Dashboard or admin are not affected.
Q: Do existing public apps need to migrate to expiring tokens? A: Existing public apps created before April 1, 2026 are not required to migrate. Migration is optional but recommended for improved security. If you choose to migrate, plan carefully to avoid service interruptions.
Q: Will Shopify’s official app templates and libraries handle expiring tokens? A: Yes. Shopify’s app templates and official libraries already implement support for expiring offline access tokens. Using these resources reduces implementation effort.
Q: How often will offline tokens expire? A: Shopify’s public documentation defines token lifetimes. Implement token expiry tracking in your app and follow Shopify’s documented values for expires_in or expiry timestamps. Architect your refresh logic to work with the expiry window and a conservative safety margin.
Q: What happens if a refresh attempt fails? A: For transient errors (network issues, rate limits), retry with exponential backoff and alert operations. For permanent errors (revoked refresh token or invalid grant), prompt the merchant to reauthorize the app via your reauthorization flow.
Q: Do webhooks require a valid offline token to be delivered by Shopify? A: No. Shopify will deliver webhooks regardless of your token’s state. If a webhook handler needs to call Shopify’s API, it must ensure the token is valid and refresh it if needed. Queue or delay processing if refresh is required and cannot complete immediately.
Q: How should apps store and protect tokens? A: Encrypt tokens at rest using a KMS, limit access via RBAC, avoid logging token values, use TLS for transmission, and rotate encryption keys and client secrets per policy. Centralize token access with a token manager service to enforce uniform handling.
Q: What are recommended strategies for background jobs and long-running processes? A: Break work into smaller tasks, validate tokens before each task, and coordinate refresh attempts using distributed locks or a central token manager. Use a safety margin to refresh tokens before they expire to avoid mid-task failures.
Q: Will Shopify revoke old non-expiring tokens at a later date? A: Shopify’s current announcement applies to new public apps created after April 1, 2026. There is no statement in this announcement about revoking tokens for apps created before that date. Stay informed via Shopify’s developer communications for any future policy updates.
Q: Where can developers get help during implementation? A: Shopify encourages engagement with the developer community forums for support and best practices. Use official SDKs and templates where possible and consult Shopify’s developer documentation for the latest technical details.
Q: How should apps handle merchant reauthorization UX? A: Provide clear, actionable messages describing why reauthorization is required, what features will be interrupted, and steps to reauthorize. Offer a simple one-click or minimal-step flow in the app admin that takes merchants back through the OAuth consent screen.
Q: How can apps avoid overwhelming Shopify’s refresh endpoints during scale? A: Stagger refresh schedules, shard shops across time windows, use distributed locks to serialize refresh per-shop, and implement exponential backoff on failures. Monitor global refresh traffic and adjust scheduling heuristics as needed.
Q: Are there best practices for monitoring token health? A: Track refresh success rates, time-to-refresh, number of shops requiring reauthorization, and unusual refresh activity. Alert on sustained refresh failures and maintain dashboards that correlate token health with merchant support tickets and app uptime.
Q: Can apps use expiring tokens for third-party integrations? A: Yes. The principles of expiring tokens and refresh flows apply to any external integration. Centralize credential management, rotate tokens regularly, and follow each provider’s recommended OAuth patterns.
Q: If my app uses third-party worker platforms (serverless or managed), how do I manage tokens there? A: Use a secure token store accessible to worker instances, keep workers stateless regarding token content, and use a token manager endpoint to supply valid tokens. Avoid embedding tokens in serverless function code or environment variables without encryption and rotation.
Q: What immediate steps should a developer building a new public app take? A: Use Shopify’s app templates or SDKs, implement secure token storage, add a robust refresh manager, test refresh and failure scenarios thoroughly, and prepare merchant-facing reauthorization workflows. Build monitoring and alerts for refresh health.
Q: Who can I contact for support if I encounter issues implementing expiring offline tokens? A: Start with Shopify’s developer documentation and the dev platform community. If you need direct assistance, use Shopify’s official support channels according to the guidance in the developer docs. Provide non-sensitive logs and error details to help diagnose issues.