StripeMeter Pricing Simulator - Getting Started
September 1, 2025 · View on GitHub
The StripeMeter Pricing Simulator is a powerful tool that helps you test different pricing strategies, validate billing logic, and optimize your revenue models before deploying to production. This guide will help you understand how to use the simulator effectively.
What is the Pricing Simulator?
The simulator allows you to:
- Test pricing models (tiered, volume, graduated) with realistic usage data
- Compare revenue outcomes between different pricing strategies
- Validate billing accuracy before customers see their bills
- Simulate complex scenarios including credits, commitments, and adjustments
- Optimize pricing for different customer segments
Quick Start
1. Basic Invoice Simulation
import { InvoiceSimulator } from '@stripemeter/pricing-lib';
const simulator = new InvoiceSimulator();
// Define your usage and pricing
const simulationInput = {
customerId: 'cust_123',
periodStart: '2024-01-01',
periodEnd: '2024-02-01',
usageItems: [
{
metric: 'api_calls',
quantity: 15000,
priceConfig: {
model: 'tiered',
currency: 'USD',
tiers: [
{ upTo: 1000, unitPrice: 0.10 }, // \$0.10 for first 1,000
{ upTo: 10000, unitPrice: 0.08 }, // \$0.08 for next 9,000
{ upTo: null, unitPrice: 0.05 } // \$0.05 for everything above
]
}
}
]
};
// Run the simulation
const invoice = simulator.simulate(simulationInput);
console.log(`Total bill: $${invoice.total}`);
2. Compare Pricing Models
const usage = 15000; // API calls
const pricingModels = {
tiered: {
model: 'tiered',
currency: 'USD',
tiers: [
{ upTo: 1000, unitPrice: 0.10 },
{ upTo: 10000, unitPrice: 0.08 },
{ upTo: null, unitPrice: 0.05 }
]
},
volume: {
model: 'volume',
currency: 'USD',
tiers: [
{ upTo: 1000, unitPrice: 0.10 },
{ upTo: 10000, unitPrice: 0.08 },
{ upTo: null, unitPrice: 0.05 }
]
},
graduated: {
model: 'graduated',
currency: 'USD',
tiers: [
{ upTo: 1000, flatPrice: 50, unitPrice: 0.05 },
{ upTo: 10000, flatPrice: 100, unitPrice: 0.03 },
{ upTo: null, flatPrice: 200, unitPrice: 0.01 }
]
}
};
// Compare results
Object.entries(pricingModels).forEach(([modelName, config]) => {
const result = simulator.simulate({
customerId: 'cust_123',
periodStart: '2024-01-01',
periodEnd: '2024-02-01',
usageItems: [{ metric: 'api_calls', quantity: usage, priceConfig: config }]
});
console.log(`${modelName}: $${result.total}`);
});
Pricing Model Types
Tiered Pricing
Each unit is priced according to the tier it falls into.
const tieredConfig = {
model: 'tiered',
currency: 'USD',
tiers: [
{ upTo: 1000, unitPrice: 0.10 }, // First 1,000 units at \$0.10
{ upTo: 10000, unitPrice: 0.08 }, // Next 9,000 units at \$0.08
{ upTo: null, unitPrice: 0.05 } // All remaining at \$0.05
]
};
// 15,000 units = (1,000 × \$0.10) + (9,000 × \$0.08) + (5,000 × \$0.05) = \$1,070
Volume Pricing
All units are priced at the rate of the tier they reach.
const volumeConfig = {
model: 'volume',
currency: 'USD',
tiers: [
{ upTo: 1000, unitPrice: 0.10 },
{ upTo: 10000, unitPrice: 0.08 },
{ upTo: null, unitPrice: 0.05 }
]
};
// 15,000 units = 15,000 × \$0.05 = \$750 (lowest applicable rate)
Graduated Pricing
Each tier has a flat fee plus a per-unit rate.
const graduatedConfig = {
model: 'graduated',
currency: 'USD',
tiers: [
{ upTo: 1000, flatPrice: 50, unitPrice: 0.05 },
{ upTo: 10000, flatPrice: 100, unitPrice: 0.03 },
{ upTo: null, flatPrice: 200, unitPrice: 0.01 }
]
};
// 15,000 units = \$200 + (15,000 × \$0.01) = \$350
Advanced Features
Credits and Commitments
const simulationWithCredits = {
customerId: 'cust_123',
periodStart: '2024-01-01',
periodEnd: '2024-02-01',
usageItems: [
{
metric: 'api_calls',
quantity: 15000,
priceConfig: tieredConfig
}
],
credits: [
{ amount: 100, reason: 'Welcome credit' },
{ amount: 50, reason: 'Referral bonus', expiresAt: '2024-03-01' }
],
commitments: [
{ amount: 500, startDate: '2024-01-01', endDate: '2024-12-31', applied: 0 }
],
taxRate: 8.5 // 8.5% tax
};
const invoice = simulator.simulate(simulationWithCredits);
console.log(`Subtotal: $${invoice.subtotal}`);
console.log(`Credits: -$${invoice.credits}`);
console.log(`Tax: $${invoice.tax}`);
console.log(`Total: $${invoice.total}`);
Multi-Metric Billing
const multiMetricSimulation = {
customerId: 'enterprise_customer',
periodStart: '2024-01-01',
periodEnd: '2024-02-01',
usageItems: [
{
metric: 'api_calls',
quantity: 50000,
priceConfig: {
model: 'tiered',
currency: 'USD',
tiers: [
{ upTo: 10000, unitPrice: 0.01 },
{ upTo: 100000, unitPrice: 0.008 },
{ upTo: null, unitPrice: 0.005 }
]
}
},
{
metric: 'data_processed_gb',
quantity: 500,
priceConfig: {
model: 'volume',
currency: 'USD',
tiers: [
{ upTo: 100, unitPrice: 0.50 },
{ upTo: 1000, unitPrice: 0.40 },
{ upTo: null, unitPrice: 0.30 }
]
}
},
{
metric: 'storage_gb_hours',
quantity: 8760, // 1 GB for full month
priceConfig: {
model: 'flat',
currency: 'USD',
unitPrice: 0.02
}
}
]
};
const invoice = simulator.simulate(multiMetricSimulation);
console.log('Invoice breakdown:');
invoice.lineItems.forEach(item => {
console.log(`${item.metric}: ${item.quantity} units × $${item.unitPrice} = $${item.subtotal}`);
});
console.log(`Total: $${invoice.total}`);
Real-World Scenarios
See Pricing Scenarios for detailed examples including:
- SaaS API Company - tiered pricing for different customer segments
- Data Processing Service - volume-based pricing with commitments
- Storage Provider - graduated pricing with minimum charges
- Enterprise Platform - complex multi-metric billing
Integration with StripeMeter
The simulator uses the same pricing calculations as the live StripeMeter system, ensuring:
- Billing accuracy - what you simulate is what customers pay
- Parity testing - validate against Stripe invoices
- Confidence - deploy pricing changes with certainty
Testing Against Live Data
// Use real usage data from your system
const realUsageData = await getCustomerUsage('cust_123', '2024-01-01', '2024-02-01');
const simulatedInvoice = simulator.simulate({
customerId: 'cust_123',
periodStart: '2024-01-01',
periodEnd: '2024-02-01',
usageItems: realUsageData.map(usage => ({
metric: usage.metric,
quantity: usage.total,
priceConfig: getPricingConfig(usage.metric)
}))
});
// Compare with actual Stripe invoice
const stripeInvoice = await stripe.invoices.retrieve('in_...');
const difference = Math.abs(simulatedInvoice.total - stripeInvoice.total);
console.log(`Difference: $${difference} (${(difference/stripeInvoice.total*100).toFixed(2)}%)`);
Best Practices
1. Start Simple
- Begin with single-metric, single-tier pricing
- Add complexity gradually as you understand the patterns
2. Test Edge Cases
const edgeCases = [
{ name: 'Zero usage', quantity: 0 },
{ name: 'Minimum tier', quantity: 1 },
{ name: 'Tier boundary', quantity: 1000 },
{ name: 'High usage', quantity: 1000000 }
];
edgeCases.forEach(testCase => {
const result = simulator.simulate({
customerId: testCase.name,
periodStart: '2024-01-01',
periodEnd: '2024-02-01',
usageItems: [{
metric: 'api_calls',
quantity: testCase.quantity,
priceConfig: tieredConfig
}]
});
console.log(`${testCase.name}: $${result.total}`);
});
3. Validate Revenue Impact
// Test pricing changes against historical data
const historicalUsage = getHistoricalUsage('last_3_months');
const currentRevenue = calculateRevenue(historicalUsage, currentPricing);
const newRevenue = calculateRevenue(historicalUsage, proposedPricing);
console.log(`Revenue impact: ${((newRevenue - currentRevenue) / currentRevenue * 100).toFixed(1)}%`);
4. Customer Segment Analysis
const segments = ['startup', 'growth', 'enterprise'];
segments.forEach(segment => {
const segmentUsage = getSegmentUsage(segment);
const avgBill = calculateAverageBill(segmentUsage, pricingConfig);
console.log(`${segment}: Average bill $${avgBill}`);
});
Next Steps
- Explore Scenarios - Check out detailed pricing scenarios
- Set up CI Testing - Automate pricing validation in your deployment pipeline
- Monitor in Production - Use reconciliation reports to ensure accuracy
- Optimize Continuously - Regular simulation helps optimize pricing strategy
Need Help?
Simulator CLI (sim) quickstart
Use the local CLI to validate scenarios, run them offline using the pricing engine, and report diffs against expected artifacts.
# Build workspace (first time or after changes)
pnpm build
# Validate all scenarios under examples/
pnpm run sim validate --dir examples
# Run scenarios and write results to results/
pnpm run sim run --dir examples --out results --seed 42
# Record the current results as expected artifacts next to scenarios
pnpm run sim run --dir examples --out results --record
# Diff actual results vs expected and fail on differences
pnpm run sim report --dir examples --results results --fail-on-diff
- Scenarios live in
scenarios/or any folder you specify (seeexamples/). - Scenario files use
.sim.jsonextension and minimally requiremetadata,inputs.usageItems, and anexpected.totalto assert. - You can set per-scenario tolerances via
tolerances.absoluteandtolerances.relativefor numeric diffs.
Example scenario skeleton:
{
"metadata": { "name": "tiered-basic", "version": "1" },
"inputs": {
"customerId": "cust_1",
"periodStart": "2024-01-01",
"periodEnd": "2024-01-31",
"usageItems": [
{
"metric": "requests",
"quantity": 350,
"priceConfig": {
"model": "tiered",
"currency": "USD",
"tiers": [
{ "upTo": 100, "unitPrice": 0.1 },
{ "upTo": 500, "unitPrice": 0.08 },
{ "upTo": null, "unitPrice": 0.05 }
]
}
}
]
},
"expected": { "total": 28.0 },
"tolerances": { "absolute": 0.001, "relative": 0.0005 }
}
CI runs validate → run → report for examples/. Place your own scenarios in scenarios/ and mirror the same commands locally.