McTaba Labs logo
Software EngineeringThe WhiteboardProjectsEventsMasterclassesWebinarsLearn
Book Call

500+ developers already in the community

Get answers, find accountability partners, and stay ahead

Join Discord →
McTaba Labs logo

Educating 1 million students in tech by 2030.

Programs

  • HighSchool Graduates Launchpad
  • AI & Business Automation
  • Corporate Training
  • McTaba Story & Mission
  • Full-Stack Curriculum
  • Course Pricing & Plans
  • Frequently Asked Questions

Resources

  • Join Discord Community
  • Tech Events in Nairobi
  • Masterclasses
  • Free Resources
  • Learn
  • Campus
  • Africa Tech Talent Report
  • Partner With Us
  • Start a Project
  • Our Work

Contact Us

  • 124 Manyani East Road, Lavington, Nairobi
  • +254727795603
  • Book a Discovery Call

Office Hours:

Mon-Fri: 9am - 2pm EAT

Sat: 10am - 12pm EAT

© 2027 McTaba Labs - A product of Edtech Industries. All rights reserved.

Privacy PolicyTerms of ServiceRefund Policy
  1. Learn
  2. Paystack for African Developers
  3. Grandfathering Old Prices on Paystack Plans
Bonaventure OgetoBy Bonaventure Ogeto|Updated July 20, 2026

Grandfathering Old Prices on Paystack Plans

Paystack plan amounts cannot be changed after creation. To raise prices, create a new plan at the new price and direct new subscribers to it. Existing subscribers stay on the old plan at the old price (grandfathering). To eventually migrate them, cancel their old subscription and create a new one on the new plan with advance notice. Archive the old plan when no subscribers remain.

In this article

  1. 1. Why Paystack Plans Are Immutable
  2. 2. The Grandfathering Strategy
  3. 3. Tracking Plan Versions
  4. 4. Migrating Grandfathered Subscribers
  5. 5. Communicating Price Changes
  6. 6. When to End Grandfathering

Why Paystack Plans Are Immutable

Once you create a Paystack plan with an amount and interval, those fields cannot be changed. This is by design. Changing a plan's price would silently change the charge amount for every subscriber, which could be catastrophic.

This immutability means price changes require a new plan. Old plan for old price. New plan for new price. Your application manages the mapping between them.

This article is part of the subscriptions and recurring billing guide.

The Grandfathering Strategy

When you raise prices, existing subscribers stay on the old plan at the old price. New subscribers sign up on the new plan at the new price. This is grandfathering.

// Step 1: Create the new plan
async function createNewPricePlan() {
  var response = await axios.post(
    'https://api.paystack.co/plan',
    {
      name: 'Pro Monthly v2',
      amount: 700000, // New price: 7,000 NGN (was 5,000)
      interval: 'monthly',
      currency: 'NGN',
      send_invoices: false,
    },
    {
      headers: {
        Authorization: 'Bearer ' + process.env.PAYSTACK_SECRET_KEY,
        'Content-Type': 'application/json',
      },
    }
  );

  return response.data.data.plan_code;
}

// Step 2: Archive the old plan (prevent new signups)
async function archiveOldPlan(oldPlanCode) {
  // Note: archiving via the Paystack Dashboard is most reliable
  // Existing subscriptions on this plan continue billing
  console.log('Archive plan ' + oldPlanCode + ' via Dashboard');
}

// Step 3: Update your application config
var PLAN_MAP = {
  pro_monthly: {
    current: 'PLN_pro_monthly_v2_xxx', // New subscribers get this
    legacy: ['PLN_pro_monthly_v1_xxx'], // Old subscribers are on these
    amount: 700000,
    legacyAmounts: { 'PLN_pro_monthly_v1_xxx': 500000 },
  },
};

Key steps:

  1. Create the new plan at the new price.
  2. Update your pricing page and checkout flow to use the new plan code.
  3. Archive the old plan so no new subscribers can sign up for it.
  4. Existing subscribers continue paying the old price with no action needed.

Get weekly developer tips

Join 25,000+ developers. Practical guides, job tips, and new content — straight to your inbox.

No spam. Unsubscribe anytime.

Tracking Plan Versions

CREATE TABLE plan_versions (
  id SERIAL PRIMARY KEY,
  tier VARCHAR(50) NOT NULL,
  version INTEGER NOT NULL,
  paystack_plan_code VARCHAR(50) UNIQUE NOT NULL,
  amount INTEGER NOT NULL,
  interval VARCHAR(20) NOT NULL,
  currency VARCHAR(3) NOT NULL,
  is_current BOOLEAN DEFAULT false,
  is_archived BOOLEAN DEFAULT false,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  archived_at TIMESTAMPTZ
);

-- Example data:
-- tier: pro, version: 1, code: PLN_xxx_v1, amount: 500000, is_current: false, is_archived: true
-- tier: pro, version: 2, code: PLN_xxx_v2, amount: 700000, is_current: true, is_archived: false
async function getCurrentPlanCode(tier, interval) {
  var result = await db.query(
    'SELECT paystack_plan_code FROM plan_versions WHERE tier = $1 AND interval = $2 AND is_current = true',
    [tier, interval]
  );
  return result.rows[0].paystack_plan_code;
}

async function isLegacyPlan(planCode) {
  var result = await db.query(
    'SELECT is_current FROM plan_versions WHERE paystack_plan_code = $1',
    [planCode]
  );
  return result.rows.length > 0 && !result.rows[0].is_current;
}

// In your billing dashboard, show whether the customer is on a legacy plan
async function getBillingDisplay(userId) {
  var billing = await getCurrentBilling(userId);
  var planVersion = await db.query(
    'SELECT tier, version, amount, is_current FROM plan_versions WHERE paystack_plan_code = $1',
    [billing.plan_code]
  );

  var pv = planVersion.rows[0];
  var isLegacy = !pv.is_current;

  return {
    planName: pv.tier + ' (v' + pv.version + ')',
    amount: pv.amount,
    isLegacyPrice: isLegacy,
    legacyMessage: isLegacy ? 'You are on a legacy price. Current price for new subscribers is higher.' : null,
  };
}

Migrating Grandfathered Subscribers

Sometimes you need to move grandfathered subscribers to the new price. This should be rare and handled carefully.

async function migrateToNewPrice(userId, newPlanCode) {
  var user = await getUser(userId);
  var billing = await getCurrentBilling(userId);
  var paymentMethod = await getDefaultPaymentMethod(userId);

  // Cancel old subscription at end of current period
  await disableSubscription(billing.paystack_subscription_code, billing.paystack_email_token);

  // Schedule migration for end of current period
  await db.query(
    'UPDATE billing_accounts SET pending_plan_change = $1, pending_change_date = $2, migration_reason = $3, updated_at = NOW() WHERE user_id = $4',
    [newPlanCode, billing.current_period_end, 'price_increase', userId]
  );

  return {
    migrationDate: billing.current_period_end,
    newPlan: newPlanCode,
  };
}

// Batch migration: migrate all subscribers on a legacy plan
async function batchMigrate(legacyPlanCode, newPlanCode) {
  var subscribers = await db.query(
    'SELECT ba.user_id FROM billing_accounts ba JOIN plan_versions pv ON ba.plan_code = pv.paystack_plan_code WHERE pv.paystack_plan_code = $1 AND ba.status = $2',
    [legacyPlanCode, 'active']
  );

  console.log('Migrating ' + subscribers.rows.length + ' subscribers from ' + legacyPlanCode + ' to ' + newPlanCode);

  for (var i = 0; i < subscribers.rows.length; i++) {
    try {
      await migrateToNewPrice(subscribers.rows[i].user_id, newPlanCode);
    } catch (error) {
      console.log('Migration failed for user ' + subscribers.rows[i].user_id + ': ' + error.message);
    }
  }
}

Always give at least 30 days notice before migrating subscribers to a higher price. 60 days is better. Send multiple notifications: 60 days, 30 days, 14 days, and 3 days before the change.

Communicating Price Changes

Price increase emails should lead with value, not with the price change. Here is a template:

Subject: Changes to your [Product] plan

Structure:

  1. Thank them for being a customer (especially long-term ones).
  2. Highlight what you have added since they subscribed (new features, improvements, reliability).
  3. State the price change clearly: old price, new price, effective date.
  4. Acknowledge the impact: "We understand this is a change."
  5. Offer alternatives: downgrade to a cheaper plan, switch to annual billing for savings, or contact support for special circumstances.

For loyal customers (subscribed for 12+ months), consider offering a transition period: 3 months at the old price before the new price kicks in. This rewards loyalty and reduces churn from the price increase.

Track churn rates in the 30-60 days following a price increase. Compare to your normal churn rate. If the spike is significant, your price increase may be too aggressive or your communication may not have conveyed enough value.

When to End Grandfathering

Grandfathering forever is not always sustainable. If your costs increase significantly, grandfathered subscribers at old prices can become unprofitable.

Decide based on:

  • Revenue impact: How much revenue are you losing to grandfathered pricing? Is it material?
  • Customer lifetime: Long-term customers who have been paying for years deserve more consideration than someone who signed up last month at the old price.
  • Competitive landscape: If competitors charge more, you have room to increase. If they charge less, the increase risks losing customers.
  • Feature parity: If grandfathered customers have access to features that now cost more, migration is easier to justify.

A common middle ground: grandfather the price for 12-24 months, then migrate to the new price with advance notice. This rewards early loyalty while ensuring pricing sustainability.

Key Takeaways

  • ✓Paystack plan amounts are immutable. You cannot change the price of an existing plan. Create a new plan for the new price.
  • ✓Existing subscribers stay on the old plan automatically. This is grandfathering by default.
  • ✓Archive the old plan to prevent new signups while keeping existing subscriptions active.
  • ✓To migrate grandfathered subscribers to the new price, give 30-60 days notice, then cancel the old subscription and create a new one.
  • ✓Track plan versions in your database. Map old and new plan codes so your application can handle subscribers on different versions.
  • ✓Price increases cause churn. Communicate the value increase alongside the price increase. Give loyal customers extra notice or a transition discount.

Frequently Asked Questions

Can I change the price of an existing Paystack plan?
No. Plan amount, interval, and currency are immutable on Paystack. To change the price, create a new plan and migrate subscribers. The old plan continues to charge the old amount until all subscribers are moved or cancel.
What happens to existing subscribers when I archive a plan?
Archiving a plan prevents new subscriptions but does not affect existing subscribers. They continue to be charged at the plan's original amount on their billing cycle. The plan remains active for them until they cancel or you migrate them.
Should I notify customers before a price increase?
Always. Give at least 30 days notice, ideally 60 days. Multiple notifications (60 days, 30 days, 14 days, 3 days) ensure the customer sees the message. Surprise price increases cause churn and damage trust.
How do I handle annual subscribers during a price increase?
Annual subscribers should keep their current price through the end of their annual term. The new price takes effect at renewal. This is both fair (they paid for the year) and legally prudent. Notify them well before the renewal date.

Learn Paystack Integration

KES 2,999

The definitive guide to building payment systems with Paystack — from your first transaction to production-grade payment infrastructure across Africa. 9 modules, 47 lessons. Free preview available.

Start Paystack Course

Not ready? Create Free Account

Keep reading

Paystack Subscriptions and Recurring Billing: Complete Guide

Everything you need to build recurring billing on Paystack. Covers the subscriptions API, plans, authorization codes for manual charges, dunning, lifecycle webhooks, cancellation, and real-world patterns for SaaS, memberships, school fees, and loan collection across Africa.

Read more

Paystack Plans and Subscriptions: The Full Data Model

A complete walkthrough of every object in the Paystack recurring billing system. Plans, subscriptions, authorizations, invoices, and customers: how they connect, what each field means, and the edge cases that trip up developers building billing for African markets.

Read more

Proration and Plan Upgrades with Paystack

Paystack does not handle proration automatically. When a customer upgrades or downgrades mid-cycle, you calculate the prorated amount, charge or credit the difference, cancel the old subscription, and create a new one. This guide provides the math, the code, and the edge cases for implementing proration on Paystack.

Read more

Cancelling and Pausing Paystack Subscriptions

Paystack lets you cancel subscriptions but has no native pause feature. This guide covers the disable API for cancellation, the difference between immediate and end-of-period cancellation, how to implement pause and resume in your application, and the reactivation flow for customers who come back.

Read more

Annual vs Monthly Billing Logic on Paystack

Offering both annual and monthly billing increases revenue and reduces churn. This guide covers creating Paystack plans for both intervals, building the pricing page toggle, handling switches between annual and monthly, proration calculations, and the business logic around annual discounts.

Read more

Explore related topics

M-Pesa & African Stack

M-Pesa Daraja API tutorials, USSD development, and WhatsApp Business API guides. The African Stack that global bootcamps do not teach.

Learn to Code in Kenya

Everything a Kenyan needs to know before writing their first line of code. Career paths, real costs, hardware requirements, and honest answers about what it takes.

Learning to Code

Roadmaps, language guides, and practical advice for learning to code and launching a programming career.

Breaking Into Tech

Practical, no-nonsense guides for anyone looking to start or change their career in tech. From choosing your first language to acing interviews.

The African Stack: Skills for This Market

The skills that make Kenyan developers hard to replace: M-Pesa, USSD, WhatsApp, fintech, and building for the African market.

Bonaventure Ogeto

Bonaventure Ogeto

Founder, McTaba Labs

Bonaventure is the founder of McTaba Labs, a coding bootcamp in Nairobi, Kenya. He has spent years building products for the African market and mentoring the next generation of developers across the continent.