What Is a Plan Management Service?
A Plan Management Service owns the catalog of subscription plans and the logic for upgrading, downgrading, and switching between them. It is a supporting service to the subscription lifecycle: while the subscription service tracks which plan a customer is on, the plan management service defines what plans exist, what they cost, what features they unlock, and how mid-cycle plan changes are prorated.
Data Model
-- Plan catalog
CREATE TABLE plans (
plan_id INT PRIMARY KEY AUTO_INCREMENT,
code VARCHAR(50) NOT NULL UNIQUE, -- e.g. 'pro_monthly'
display_name VARCHAR(100) NOT NULL,
price_cents INT NOT NULL,
currency CHAR(3) NOT NULL DEFAULT 'USD',
interval ENUM('monthly','annual') NOT NULL,
trial_days INT NOT NULL DEFAULT 0,
is_public BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
-- Feature entitlements per plan
CREATE TABLE plan_features (
plan_id INT NOT NULL REFERENCES plans(plan_id),
feature_key VARCHAR(100) NOT NULL,
feature_value VARCHAR(255) NOT NULL, -- e.g. 'seats=10', 'storage_gb=100'
PRIMARY KEY (plan_id, feature_key)
);
-- Change history (proration ledger)
CREATE TABLE plan_changes (
change_id BIGINT PRIMARY KEY AUTO_INCREMENT,
subscription_id BIGINT NOT NULL,
old_plan_id INT NOT NULL,
new_plan_id INT NOT NULL,
effective_at TIMESTAMP NOT NULL,
proration_cents INT NOT NULL DEFAULT 0, -- positive = credit, negative = charge
reason ENUM('upgrade','downgrade','admin') NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
Core Algorithm: Proration
When a customer switches plans mid-cycle, the service must calculate a prorated credit or charge. The standard algorithm:
- Compute days remaining in the current period:
days_left = (period_end - NOW()) / 86400. - Compute total days in the period:
period_days = (period_end - period_start) / 86400. - Credit for unused old plan:
credit = old_price_cents * (days_left / period_days). - Charge for new plan remainder:
charge = new_price_cents * (days_left / period_days). - Net proration:
charge - credit. Positive = bill now. Negative = apply as account credit.
All arithmetic is done in integer cents with explicit rounding rules (round half-up) documented and tested. Never use floating-point for money.
Plan Change Workflow
- Immediate upgrade: apply new plan now, charge proration immediately.
- Downgrade at period end: set
pending_plan_idon subscription; apply at renewal to avoid prorating a lower price mid-cycle. - Admin override: support zero-proration plan moves for support cases, recorded with
reason='admin'and an actor user ID.
Failure Handling
Plan changes that include a charge must wrap the proration payment and the subscription update in a distributed saga: charge first, then update the subscription. If the payment fails, the plan change is rolled back and the customer remains on their current plan. Store plan_changes rows with a status column (pending, applied, failed) and process them transactionally.
Scalability Considerations
- The plan catalog is small and read-heavy. Cache the full catalog in application memory, refreshed every 5 minutes. A single cache miss is acceptable; stampede protection is not needed at this scale.
- Feature entitlement lookups (what can this user do?) should be served from the cache, not a per-request DB join.
- Plan changes are infrequent relative to reads. A write to
plan_changesplus a subscription update is the hot write path; a single writer per subscription (using optimistic locking on aversioncolumn) prevents concurrent change conflicts.
Summary
Plan Management is a catalog plus a proration calculator plus a change ledger. The catalog should be cached aggressively. Proration must be integer arithmetic with explicit rounding. Plan changes that involve money must use a saga pattern to stay consistent across the payment gateway and the subscription database. Separating immediate upgrades from deferred downgrades keeps billing surprises to a minimum.
{
“@context”: “https://schema.org”,
“@type”: “FAQPage”,
“mainEntity”: [
{
“@type”: “Question”,
“name”: “What is plan management in the context of system design?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “Plan management is the subsystem responsible for defining, storing, and enforcing the rules of subscription tiers — including pricing, feature entitlements, usage limits, and trial policies. It acts as the source of truth that the billing engine, access control layer, and customer portal all query to determine what a subscriber is allowed to do.”
}
},
{
“@type”: “Question”,
“name”: “How do you handle plan upgrades and downgrades without losing billing accuracy?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “Use proration: when a subscriber changes plans mid-cycle, calculate the unused credit on the old plan and the prorated charge for the new plan based on the exact timestamp of the change. Store a line-item ledger per billing period so every charge can be audited. Apply upgrades immediately and schedule downgrades to take effect at the end of the current billing period to avoid service disruption.”
}
},
{
“@type”: “Question”,
“name”: “How should feature entitlements be enforced at runtime for different plans?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “Maintain an entitlement service that maps (account_id, feature_key) -> allowed/limit. On each API request, the application checks the entitlement service (backed by a low-latency cache like Redis) rather than querying the plan database directly. When a plan changes, publish an event that invalidates and refreshes the affected account’s entitlement cache to keep enforcement consistent without stale data.”
}
},
{
“@type”: “Question”,
“name”: “What database schema considerations matter most for plan management?”,
“acceptedAnswer”: {
“@type”: “Answer”,
“text”: “Store plans as versioned, immutable records: never mutate an existing plan row that active subscriptions reference. Use a plan_versions table linked from the subscriptions table so historical billing can always reconstruct exactly what features and price applied at any past point in time. A separate plan_features junction table lets you add or remove entitlements per plan without schema changes.”
}
}
]
}
See also: Stripe Interview Guide 2026: Process, Bug Bash Round, and Payment Systems
See also: Shopify Interview Guide
See also: Scale AI Interview Guide 2026: Data Infrastructure, RLHF Pipelines, and ML Engineering