Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

Shopify Subscription App Development

By Kokil Thapa | Last reviewed: August 2026

Building a recurring revenue model requires precise execution of Shopify subscription app development, not just installing a pre-made plugin. Merchants often need custom billing logic, specific delivery schedules, or localized payment gateways that off-the-shelf solutions cannot provide. This guide covers the architectural realities of building subscription apps on the 2026 Shopify platform, from Billing API integration to handling complex contract states.

Before writing a single line of code, understand that subscription apps are fundamentally different from standard Shopify apps because they own critical post-purchase infrastructure. If your app fails, the merchant loses revenue immediately. For teams evaluating whether to build custom or configure existing tools, reading about Shopify vs WooCommerce comparisons provides essential context on platform trade-offs before committing to the Shopify ecosystem. In my experience shipping eCommerce systems, the decision to build a custom subscription layer usually stems from unique business rules around bundling, regional payment methods like eSewa or Khalti, or complex B2B contract terms that generic apps simply do not support.

How does the Shopify Subscription Contracts API work?

The core of modern Shopify subscription app development is the Subscription Contracts API. Unlike legacy implementations that created draft orders manually, the Contracts API treats subscriptions as first-class citizens within Shopify Admin. This means merchants can view, edit, and pause subscriptions directly in their dashboard without leaving Shopify.

Understanding Contract States

A subscription contract moves through a strict state machine. You cannot arbitrarily update fields; transitions must follow valid paths. The primary states include:

  • ACTIVE: The subscription is live and will generate orders on the next billing cycle.
  • PAUSED: Billing is temporarily halted. No orders are generated until resumed.
  • CANCELLED: Terminal state. The contract cannot be reactivated; a new one must be created.
  • EXPIRED: Reached its defined end date or maximum number of billing cycles.
  • FAILED: Payment could not be processed after all retry attempts.

In practice, most bugs occur when developers attempt invalid transitions, such as trying to update line items on a CANCELLED contract. Always validate state before mutation.

Subscription Contract LifecycleACTIVEPAUSEDFAILEDCANCELLED / EXPIREDPausePayment FailCancel/ExpireCancelMax Retries
Valid state transitions for Shopify Subscription Contracts API prevent data corruption

Mandatory Webhooks

You cannot poll for subscription changes. Your app must subscribe to these mandatory topics during installation:

<!-- Required webhook subscriptions in shopify.app.toml -->
[[webhooks.subscriptions]]
topics = [ "SUBSCRIPTION_CONTRACTS_CREATE" ]
uri = "/api/webhooks/contracts/create"

[[webhooks.subscriptions]]
topics = [ "SUBSCRIPTION_CONTRACTS_UPDATE" ]
uri = "/api/webhooks/contracts/update"

[[webhooks.subscriptions]]
topics = [ "SUBSCRIPTION_BILLING_ATTEMPTS_CHALLENGED" ]
uri = "/api/webhooks/billing/challenged"

Missing any of these will cause your app to fail verification. The SUBSCRIPTION_BILLING_ATTEMPTS_CHALLENGED webhook is particularly critical for 3D Secure flows in regions like Nepal and India where SCA/RBI regulations require customer authentication.

What are the best practices for implementing Selling Plans?

Selling Plans define the purchasing options presented to customers on the product page. They link products to subscription contracts via the Storefront API. A common mistake in Shopify subscription app development is creating overly rigid selling plans that force merchants into binary choices.

Structuring Flexible Pricing Policies

Your selling plan should support multiple pricing adjustments simultaneously. For example, a "Subscribe & Save" offer might include both a percentage discount and free shipping. Use the GraphQL Admin API to create these structures:

mutation CreateSellingPlanGroup {
  sellingPlanGroupCreate(input: {
    name: "Weekly Coffee Subscription"
    merchantCode: "COFFEE-WEEKLY"
    options: ["Delivery Frequency"]
    position: 1
    sellingPlansToCreate: [{
      name: "Deliver every week"
      options: ["1 Week"]
      billingPolicy: {
        recurring: {
          interval: WEEK
          intervalCount: 1
        }
      }
      deliveryPolicy: {
        recurring: {
          interval: WEEK
          intervalCount: 1
        }
      }
      pricingPolicies: [{
        fixed: {
          adjustmentType: PERCENTAGE
          adjustmentValue: 15
        }
      }]
    }]
  }) {
    sellingPlanGroup {
      id
      sellingPlans(first: 5) {
        nodes { id name }
      }
    }
    userErrors { field message }
  }
}

Note that merchantCode must be unique per group. Reusing codes causes silent failures during product association. I have seen this break entire catalog integrations during migrations.

Product Association Strategy

Do not associate selling plans with individual variants unless absolutely necessary. Associate at the product level whenever possible. Variant-level associations create maintenance nightmares when merchants add new sizes or colors. If you must use variant-level granularity, implement an automated sync job that propagates new variants to existing selling plan groups.

How do you handle billing cycles and payment failures?

Billing reliability separates production-grade subscription apps from prototypes. Shopify handles the actual charge, but your app orchestrates the attempt schedule and failure response.

Dunning Management Logic

When a payment fails, Shopify triggers SUBSCRIPTION_BILLING_ATTEMPTS_CHALLENGED. Your app must decide whether to retry, notify, or cancel. Implement exponential backoff with jitter to avoid thundering herd problems if a payment processor experiences partial outage:

  1. Attempt 1 (Day 0): Immediate retry. Many failures are transient network issues.
  2. Attempt 2 (Day 3): Send email notification to customer with update-payment link.
  3. Attempt 3 (Day 7): Final retry. If failed, move contract to FAILED state.
  4. Grace Period (Day 14): If still unresolved, transition to CANCELLED or PAUSED based on merchant configuration.

Store retry metadata in app-owned storage, not in Shopify metafields. Metafields have size limits and are not designed for high-frequency transactional logging.

Payment Failure Recovery PipelinePayment FailedWebhook ReceivedRetry #1Immediate + JitterRetry #2Day 3 + Email AlertRetry #3Day 7 Final AttemptSuccessSuccessContract FAILEDTrigger Dunning EndLog All Attempts to App Database (Not Metafields)
Exponential backoff with customer notifications prevents churn during payment processing failures

Regional Payment Considerations

For merchants serving South Asian markets, standard Stripe/PayPal billing may not suffice. When integrating local gateways like eSewa, Khalti, or ConnectIPS, remember that many do not support true recurring billing tokens. In these cases, you must implement a "billing agreement" flow where the customer authorizes future charges via OTP, then your app initiates subsequent charges server-side. This pattern is documented in my article on Laravel Khalti and eSewa payment integration and applies equally to Shopify app backends built with Node.js or PHP.

Custom vs native subscription solutions comparison

Not every merchant needs custom Shopify subscription app development. Understanding when to build versus when to configure saves significant engineering budget.

CriteriaNative Apps (Recharge/Skio)Custom App Development
Time to LaunchDays to weeksMonths (3-6 typical)
Monthly Cost$99-$999+ USD plus transaction feesHosting + maintenance (~$50-200 USD/mo)
Customization CeilingLimited to app's exposed settings/APIUnlimited (full API access)
Local Payment SupportRarely supports NPR/regional gatewaysFull control over payment orchestration
Data OwnershipVendor lock-in, export difficultiesComplete ownership of contract data
Maintenance BurdenZero (vendor managed)High (you own uptime, security, upgrades)
Best ForStandard DTC subscription boxesB2B, regional markets, complex bundles

If your requirements fit within a native app's capabilities, use it. Custom development only makes sense when you hit hard ceilings: regulatory compliance, unsupported payment rails, or business logic that would cost more in native app overages than building from scratch.

How do you secure subscription app data and comply with GDPR?

Subscription apps handle sensitive PII and financial metadata. Security is non-negotiable.

Session Token Authentication

Never use legacy cookie-based auth. All 2026 Shopify apps must use session tokens signed by Shopify. Validate the HMAC signature on every request. Store session tokens securely and rotate them according to Shopify's TTL recommendations.

Data Minimization and Retention

Only store what you need for billing operations. Do not cache full customer profiles. Implement automated data deletion workflows triggered by the CUSTOMERS_DATA_REQUEST and CUSTOMERS_REDACT mandatory webhooks. These are required for GDPR compliance and app store approval.

API Rate Limit Management

Subscription apps generate high API call volumes during billing cycles. Implement leaky bucket rate limiting in your app backend. Monitor cost.throttled fields in GraphQL responses. Batch operations using bulkOperationRunMutation for large-scale contract updates rather than individual calls. Teams familiar with backend optimization patterns from frameworks like Laravel will find similar principles apply; see Laravel API best practices for transferable rate-limiting strategies.

App Security & Compliance LayersShopify AdminIssues Session TokenApp BackendValidates HMAC SignatureEnforces Rate LimitsDatabaseMinimal PII StorageGDPR Compliance LayerCUSTOMERS_DATA_REQUEST • CUSTOMERS_REDACT • SHOP_REDACT WebhooksRate Limit ProtectionLeaky Bucket Algorithm • Bulk Operations • Cost Query Monitoring
Multi-layer security architecture ensures GDPR compliance and protects against API abuse

What testing strategies prevent subscription billing bugs?

Testing subscription apps is uniquely difficult because time-dependent logic cannot be easily accelerated. Standard unit tests miss race conditions in billing cycles.

Shopify Partner Dashboard Test Stores

Use unlimited test stores in your Partner account. Never test billing logic on development stores with real payment gateways enabled. Configure test gateway providers that simulate success, failure, and 3DS challenges deterministically.

Time Travel Testing

Implement a debug-only endpoint that advances contract billing dates without actually waiting. This allows QA to validate dunning sequences, renewal notifications, and expiration logic in minutes rather than weeks. Guard this endpoint behind strict environment checks and never deploy to production.

Webhook Replay Testing

Capture real webhook payloads from test stores and replay them against your local/staging environment. Tools like ngrok or Shopify CLI tunneling facilitate this. Verify idempotency by replaying the same webhook multiple times; your handler must produce identical results without duplicate side effects.

Conclusion

Successful Shopify subscription app development demands respect for platform constraints, rigorous testing of time-sensitive billing logic, and honest assessment of whether custom development truly serves the merchant better than configured alternatives. The Contracts API and Selling Plans provide powerful primitives, but they punish sloppy implementation with immediate revenue impact. Build with defensive coding practices, prioritize webhook reliability over feature velocity, and maintain clear documentation for merchants who depend on your app for recurring income.

If you are planning a subscription app project or need architectural review for an existing implementation, reach out to discuss your specific requirements. I help teams navigate the technical and business trade-offs of custom Shopify development with practical, production-focused guidance.

Frequently Asked Questions

It is building custom applications using the Shopify Subscriptions API and Admin API to manage recurring billing, fulfillment schedules, and customer portals beyond native platform capabilities.

Custom builds typically range from NPR 300,000 to NPR 800,000 (USD 2,250–6,000) depending on billing logic complexity, third-party gateway integrations, and portal customization requirements for Nepal or global markets.

Build custom when you need unique billing cycles, specific local payment gateways like eSewa or Khalti, or complex bundling logic that existing apps cannot support without expensive enterprise plans.

You must use the Shopify Subscriptions API for contract management and the Admin API for product and order manipulation. The Selling Plans API defines pricing policies and delivery frequencies, while webhooks handle asynchronous events like contract pauses, cancellations, or payment failures. All interactions require OAuth 2.0 authentication with granular scopes. In my experience integrating these for eCommerce clients, proper webhook verification is critical because missed events cause silent billing desynchronization between your app and Shopify's internal ledger.

Yes, but it requires custom development since Shopify Payments does not support recurring billing for Nepal-based merchants. You must implement a custom payment extension using the Payment Extensions API to tokenize cards or handle redirect flows for eSewa, Khalti, or ConnectIPS. The subscription contract remains in Shopify while actual charges occur via your external gateway. I have built similar integrations where we store transaction references locally and reconcile them against Shopify contracts daily to prevent fulfillment of unpaid orders during gateway downtime.

Use the Subscription Contracts API to programmatically create active contracts matching historical billing states. Map legacy customer IDs to Shopify Customer IDs first, then import contracts with correct next_billing_date values to avoid double-charging. Always set initial status to ACTIVE only after verifying payment method validity. On a recent migration project involving thousands of subscribers, we processed imports in batches of 100 with rate-limit backoff and maintained an audit log mapping old IDs to new contract IDs for future reconciliation and customer support queries.

Store normalized subscription events locally rather than querying Shopify repeatedly. Create tables for contracts, billing_attempts, fulfillment_orders, and customer_events with proper indexing on contract_id and occurred_at columns. Sync data via webhooks into this local store for fast dashboard queries. PostgreSQL works well here due to JSONB support for flexible metadata. In production subscription systems I maintain, this pattern reduces admin dashboard load times from seconds to milliseconds while providing reliable historical reporting independent of Shopify API rate limits or temporary outages.

Subscribe to subscriptions_billing_attempt_failed webhooks and log the error_code and error_message fields immediately. Common causes include expired payment tokens, insufficient funds, or gateway timeouts. Implement automatic retry logic with exponential backoff respecting Shopify's recommended retry schedule. Never silently swallow these events. On client projects, I configure alerts for consecutive failures exceeding three attempts so support teams can proactively contact customers before churn occurs. Always correlate webhook timestamps with your payment gateway logs to distinguish between Shopify-side and processor-side failures.

Store only encrypted payment tokens, never raw card data. Validate all webhook HMAC signatures before processing. Use scoped OAuth tokens with minimum required permissions. Encrypt customer PII at rest and enforce TLS 1.3 for all API communication. Implement IP allowlisting for admin endpoints and audit logging for contract modifications. Since subscription apps handle recurring financial obligations, treat every endpoint as financially sensitive. I follow PCI-DSS SAQ-A compliance patterns even when using tokenized payments because regulatory expectations in Nepal and internationally continue tightening around recurring billing software.

Selling plans define reusable pricing and delivery policies attached to products, like "Subscribe & Save 10% monthly." Subscription contracts are individual customer agreements created when someone purchases using a selling plan. One selling plan generates many contracts. Changes to a selling plan affect future purchases only; existing contracts retain their original terms unless explicitly updated via API. Confusing these causes bugs where price updates unexpectedly alter active subscriptions. Always version selling plans when changing terms and migrate existing contracts deliberately through explicit customer consent workflows rather than implicit backend updates.

Vue.js or Alpine.js integrated with Liquid templates provides lightweight interactivity without full SPA complexity. Use Shopify's App Bridge for embedded admin UIs and Polaris components for consistent design. For customer-facing portals, server-rendered Liquid with Alpine handles pause, skip, and swap actions via fetch calls to your app proxy. Avoid heavy frameworks unless portal complexity justifies build overhead. On eCommerce projects I have shipped, this approach keeps page loads under two seconds while providing responsive subscription management. Remember that portal performance directly impacts support ticket volume for simple self-service tasks.

Use Shopify's development stores with test mode enabled for the Subscriptions API. Create test selling plans and simulate billing attempts using mock payment extensions. Leverage the Shopify CLI to tunnel local development servers for webhook testing. Seed databases with synthetic contract data matching production schemas. Never test against live stores without explicit merchant approval and sandbox payment credentials. In my development workflow, I maintain separate staging environments with anonymized production snapshots to validate migration scripts and edge cases like partial refunds or mid-cycle plan changes before any deployment touches real subscriber data.

Unoptimized webhook handlers causing processing delays, excessive Admin API calls during bulk operations, and missing database indexes on frequently queried contract fields. Rate limiting compounds these issues during peak billing windows. Implement queue-based webhook processing with idempotency keys to handle retries safely. Cache selling plan configurations aggressively since they change infrequently. Batch API mutations using GraphQL bulk operations instead of REST loops. On high-volume subscription platforms, I have seen these optimizations reduce billing cycle processing time by over seventy percent while staying within Shopify's documented throughput ceilings and avoiding throttled responses during critical renewal periods.

Calculate prorated amounts based on remaining days in current billing cycle versus new plan price. Use the Subscription Contract Update mutation with proration_behavior set to CREATE_PRORATIONS for automatic adjustment invoices. Document proration logic clearly in customer-facing portals to prevent confusion. Test edge cases like mid-cycle upgrades followed by immediate downgrades. Store calculation breakdowns locally for dispute resolution. In legal-tech adjacent billing systems I have worked on, transparent proration records reduced chargeback rates significantly because customers could verify exact credit calculations. Always provide itemized explanations in confirmation emails showing original amount, credit applied, and new charge total.

Budget monthly hours for Shopify API version upgrades, webhook schema changes, payment gateway SDK updates, and security patches. Monitor deprecation notices quarterly since Shopify sunsets API versions annually. Maintain regression test suites covering billing flows, portal actions, and webhook processing. Plan for annual dependency audits and penetration testing. Subscription apps are living systems tied to financial infrastructure, not static codebases. Based on maintaining multiple production subscription integrations, ongoing maintenance typically requires ten to fifteen percent of initial development effort monthly to ensure continued reliability, compliance, and compatibility with evolving platform capabilities and merchant expectations.

Share this article

Quick Contact Options
Choose how you want to connect me: