RBI’s New Rules for Recurring Payments

The Reserve Bank of India (RBI) directive from October 2021 introduced significant changes for recurring payments. All recurring charges now require a one-time payer authorization via an e-mandate, registered through an Additional Factor of Authentication (AFA). Payments up to the RBI threshold amount can be automatically collected once the e-mandate is in place, but any amount above that threshold requires a fresh AFA per transaction. Additionally, payers must receive a pre-debit notification at least 24 hours before every charge.

For Shopify’s billing platform, addressing this framework meant partnering with a local payment provider that could support both card-based transactions and the Unified Payments Interface (UPI), a prominent local payment method. From a backend perspective, the internal payment service had to adapt to a new reality, needing to:

  • model the e-mandate concept for the first time
  • distinguish between recurring and one-time payments
  • work with both cards and UPI
  • integrate all of this with a new provider

A New Way to Think About Sources

An e-mandate is a standing instruction from a user authorizing Shopify to charge their payment method, either regularly or as needed. Registration is initiated with a small, temporary authorization hold, typically ₹1, that prompts an AFA. Once the user completes the AFA, the hold is released and the e-mandate is registered with the payment provider, which returns a token for future charges.

The payment service already had a concept that closely resembled this: the source object, which encapsulates the underlying payment method. By associating the e-mandate token with the source’s remote_reference, the team could build the e-mandate functionality with minimal disruption.

Entity-relationship diagram of the payment service’s source and charge models
Entity-relationship diagram of the payment service’s source and charge models.

Verification Semantics

A key design decision was whether to treat the source or the charge as the subject of verification. The provider verified the charge, but the payment service had historically attached verification to the source. Continuing to treat the source as the verified subject made sense in the business logic because it was the payment method itself being vetted. To keep an accurate audit trail of funds movement, the service still created a charge record that was automatically refunded asynchronously.

That distinction was important because older onboarding flows relied on authorization charges that expired automatically. In this case, real funds were moved briefly, requiring explicit handling of the temporary transaction.

Recurring vs. One-Time

The billing platform handles both recurring obligations like monthly bills and one-time purchases such as domains. The payment provider’s native onboarding produced separate tokens for each payment type, with an AFA for every card tokenization—but only one for UPI. Requiring both tokens would have forced users to complete two consecutive AFA challenges when saving a card, creating friction and awkward edge cases if the first succeeded but the second failed.

The team chose to tokenize once for recurring payments and use that token for both recurring and one-time charges. While the user experience becomes slightly odd—purchasing a theme triggers a notification of an imminent charge—it avoided double authentication. That tradeoff was acceptable in the short term, with the understanding that the provider would eventually offer a more streamlined native solution.

Card Implementation

For cards, the onboarding path routes through a PCI-compliant server before redirecting the merchant to their bank for the AFA step. This keeps sensitive card data within the secure ecosystem while keeping the authorization flow straightforward.

Chart showing onboarding a card through the payment service
Onboarding a card through the payment service. View full-size image.
Making subsequent card payments up to the RBI threshold amount through the payment service.
Making subsequent card payments up to the RBI threshold amount through the payment service. View full-size image.
Making subsequent card payments greater than the RBI threshold amount through the payment service.
Making subsequent card payments greater than the RBI threshold amount through the payment service. View full-size image.

UPI AutoPay Nuances

Launched by the National Payments Corporation of India in 2016, UPI is a mobile-only method with many competing third-party applications managing user accounts and payments. Unlike cards, the onboarding is asynchronous—the AFA arrives as a notification on the user’s phone, and they approve or reject it within their UPI app.

E-mandates registered for UPI route subsequent charges via UPI AutoPay. A notification is always issued at least 24 hours before any charge. This workflow presented a particularly difficult backend issue around e-mandate limits. The API permitted card e-mandates to charge amounts above the configured maximum, but UPI was a hard ceiling—a higher charge failed immediately. Different banks set different recurring transaction limits for UPI, and the specific UPI application also played a role in determining the limit.

UPI recurring transaction limit by bank = x ₹10,000
Daily transaction limit by bank = y ₹20,000
UPI recurring transaction limit by application = z ₹5,000
Overall UPI recurring transaction limit = min(x, y, z) ₹5,000

Since these limits could not be determined at runtime, the team decided to set ₹5,000 as the maximum amount on UPI e-mandates, because that was the lowest common recurring limit across banks and applications. Charges at or below that amount collect automatically. A charge above it redirects the user to the admin dashboard for manual completion, treated as an on-session one-time payment because the user actively accepts the transaction in their mobile app.

Onboarding a UPI account through the payment service.
Onboarding a UPI account through the payment service. View full-size image.

For amounts above ₹5,000, that manual flow deviates from the hands-off UPI e-mandate process, requiring active user participation each time.

Making subsequent UPI payments greater than ₹5,000 through the payment service.
Making subsequent UPI payments greater than ₹5,000 through the payment service. View full-size image.

Resiliency Through Idempotency

The internal payment service is the mechanism that lets products like Billing move money, so it must handle downstream failures without unpredictable behavior such as double charges. The safety net is idempotency: identical, repeated requests must return the same response. An idempotency key makes this work by acting as the unique identifier for a request.

Charging with the new provider involved two separate API calls: creating an order and then creating a payment. Neither was idempotent, but the Orders API enforced uniqueness on the receipt field—passing a duplicate value returned an error. This became an effective point of control, serving as a substitute for a proper idempotency key.

Overview of resilient order and payment creation between the payment service and Shopify’s payment provider for India.
Overview of resilient order and payment creation between the payment service and Shopify’s payment provider for India.

The reasoning and handling are arguably the most critical part of the integration, visible in the logic that guards against the failure case of a lost response between the two backend calls.

Request object which would contain details to execute the order creation API request. It will also contain methods in case recovery is needed for idempotency.
Client class is responsible for executing the API request and returning a result. In this case, it would run the recovery request if the original request was recoverable by its response.

Without that protection, a network hiccup or provider timeout could lead to a second order being created for what was, from the user’s perspective, a single transaction.

Next Steps and Lessons Learned

With the new billing implementation in place, Shopify is shifting USD-based invoices to INR for Indian merchants. Outstanding USD invoices will be reissued with a foreign exchange rate applied, and the logic for handling non-payment will be updated. Merchants will see reissued invoices in their local currency, know when they are due, and be able to settle them individually.

A few short-term decisions were made during delivery, but each was made with future iterations in mind. Once enough use cases exist, Shopify plans to explicitly model an e-mandate object and a tokenized card payment instrument within its payment service.

The RBI's regulations introduced friction for larger recurring payments by design, to curb fraudulent automatic transactions. Shopify intends to closely monitor success rates on larger transactions and adjust if they falter. Given how new these regulations are, further ecosystem changes are expected — such as e-mandate limits increasing to ₹15,000 or cards being added within UPI accounts. Any such updates will be tracked closely to see how they affect the product.

Takeaways from the Implementation

The project surfaced both technical and non-technical lessons worth capturing.

Mission Over Perfection

The core goal was simple: users must be able to pay their bills. Anything beyond that was a bonus. Early on, the team was overly self-critical about minor UX degradations. Outside feedback revealed that small inconveniences are tolerable when the primary flow works — a better approach is to aim high and refine iteratively rather than chase perfection upfront.

Short-Term Compromises Need Long-Term Context

Regulatory navigation forced many timely decisions between imperfect options. Having a sustainable long-term strategy in mind made those trade-offs easier to evaluate and helped pinpoint where pain points existed and how they might be addressed months down the line.

Extract Shared Logic Early

Multiple systems needed to talk to the payment provider's API. Rather than duplicate that pattern across repositories, Shopify abstracted the Shopify-specific logic into an internal Ruby on Rails gem. That de-duplication simplified work for each system in the latter half of the project and positioned the team for future integrations with the same provider.

Cross-Border Collaboration Takes Real Planning

The Shopify team was mostly in EST while the payment provider was in IST — a 9.5-hour gap. Meetings inevitably fell at odd hours for one side, and Slack messages took a full business day to get replies. The provider also preferred video calls over Shopify's messaging-first culture, on both sides required adjustment. These dynamics need to be factored into planning as global expansion continues.

Providers Change, Patterns Don't Always Translate

Deep experience with North American and European markets didn't transfer cleanly to a new Indian provider. Each provider brings distinct API design philosophies, and each integration challenges existing system assumptions. The project reinforced the need to build better abstractions and stay flexible across markets.

Regulations Demand Research Before Code

When regulations change, complete clarity doesn't arrive all at once. This project required significant time exploring the problem space and asking questions before meaningful code could be written. The upfront diligence on API constraints and regulatory details paid off, even though it delayed the build phase.

Parallelize Production Testing

The cards solution required 24-48 hours per QA cycle due to pre-debit notification windows and charge attempt delays. Bugs meant re-running the entire cycle. For UPI, production testing began as early as possible during the build phase, which brought the backend to a stable state sooner and cut total iteration time significantly.

Familiarity Doesn't Equal Simplicity

Cards felt like familiar territory, yet the regulatory changes completely redefined how recurring card payments worked in Shopify's systems. UPI, an asynchronous payment method unlike anything else on the billing platform, proved simpler to implement despite being unfamiliar. Familiarity alone isn't a reliable predictor of implementation complexity.

Where Things Stand

Since the card solution left beta and became widely available, billing success rates in India have risen above pre-project levels. The UPI solution is slated for general availability to all Indian merchants with local currency pricing. The road ahead will involve continued fine-tuning of the payment experience as the regulatory landscape evolves.