Pull Model
Prices as Code version 3.4.0 introduces a new "Pull Model" that complements the existing Push Model. This guide explains what the Pull Model is, why it's valuable, and how to use it to import existing pricing from providers into your codebase.
What is the Pull Model?
The Pull Model refers to the ability to:
- Extract product and pricing information from your provider (e.g., Stripe)
- Convert this information into a local configuration file (YAML, JSON, or TypeScript)
- Create a starting point for managing your existing pricing using Prices as Code
This is the opposite of the Push Model, where your local configuration is pushed to providers. With the Pull Model, your provider's data is the source of truth that initializes your local configuration.
Benefits of the Pull Model
1. Onboard Existing Customers
If you already have pricing configured in providers like Stripe, you can pull that configuration into your codebase without having to recreate it manually. This is especially helpful when adopting Prices as Code for an existing product with established pricing.
2. Configuration Backup
Create point-in-time backups of your pricing configuration, which can be useful for auditing, recovery, or comparison purposes.
3. Multi-Environment Migration
Pull configuration from one environment (e.g., production), modify it as needed, and push it to another environment (e.g., staging or development).
4. Understanding Provider Data
See exactly how your provider stores your pricing data and how Prices as Code maps between your configuration and the provider's API.
Using the Pull Model
Using the CLI
Use the pull
command with the CLI to generate a configuration file:
# Pull pricing data into a YAML file (default format)
npx prices-as-code pull pricing.yml
# Pull pricing data into a TypeScript file
npx prices-as-code pull --format=ts pricing.ts
# Pull pricing data into a JSON file
npx prices-as-code pull --format=json pricing.json
Using the JavaScript/TypeScript API
import { pac } from 'prices-as-code';
async function pullPricing() {
try {
const result = await pac.pull({
configPath: './pricing.yml', // Output file path
providers: [
{
provider: 'stripe',
options: {
secretKey: process.env.STRIPE_SECRET_KEY,
}
}
],
format: 'yaml', // 'yaml', 'json', or 'ts'
});
console.log('Pull complete:', result);
} catch (error) {
console.error('Pull failed:', error);
}
}
Configuration Format Options
The Pull Model supports three output formats:
YAML (Default)
YAML provides a clean, readable format that's easy to edit manually:
products:
- provider: stripe
name: Premium Plan
id: prod_xxxxxxxx
description: Our best value option
key: premium_plan
features:
- Unlimited projects
- Priority support
- Custom reporting
highlight: true
metadata:
displayOrder: 2
stripeCreated: '1712345678'
prices:
- provider: stripe
name: Premium Monthly
id: price_xxxxxxxx
nickname: Premium Monthly
unitAmount: 1999
currency: USD
type: recurring
recurring:
interval: month
intervalCount: 1
productId: prod_xxxxxxxx
productKey: premium_plan
key: premium_monthly
metadata:
original_name: Premium Monthly
stripeCreated: '1712345679'
TypeScript
TypeScript provides strong typing and integrated support in your codebase:
/**
* This file is auto-generated by prices-as-code.
* Manual changes may be overwritten.
*/
import { Config } from 'prices-as-code';
export const config: Config = {
products: [
{
provider: "stripe",
name: "Premium Plan",
id: "prod_xxxxxxxx",
description: "Our best value option",
key: "premium_plan",
features: [
"Unlimited projects",
"Priority support",
"Custom reporting"
],
highlight: true,
metadata: {
displayOrder: 2,
stripeCreated: "1712345678"
}
}
],
prices: [
{
provider: "stripe",
name: "Premium Monthly",
id: "price_xxxxxxxx",
nickname: "Premium Monthly",
unitAmount: 1999,
currency: "USD",
type: "recurring",
recurring: {
interval: "month",
intervalCount: 1
},
productId: "prod_xxxxxxxx",
productKey: "premium_plan",
key: "premium_monthly",
metadata: {
original_name: "Premium Monthly",
stripeCreated: "1712345679"
}
}
]
};
export default config;
JSON
JSON provides a format that's easy to parse and work with programmatically:
{
"products": [
{
"provider": "stripe",
"name": "Premium Plan",
"id": "prod_xxxxxxxx",
"description": "Our best value option",
"key": "premium_plan",
"features": [
"Unlimited projects",
"Priority support",
"Custom reporting"
],
"highlight": true,
"metadata": {
"displayOrder": 2,
"stripeCreated": "1712345678"
}
}
],
"prices": [
{
"provider": "stripe",
"name": "Premium Monthly",
"id": "price_xxxxxxxx",
"nickname": "Premium Monthly",
"unitAmount": 1999,
"currency": "USD",
"type": "recurring",
"recurring": {
"interval": "month",
"intervalCount": 1
},
"productId": "prod_xxxxxxxx",
"productKey": "premium_plan",
"key": "premium_monthly",
"metadata": {
"original_name": "Premium Monthly",
"stripeCreated": "1712345679"
}
}
]
}
Workflow Patterns
Initial Pull and Subsequent Push
A common workflow involves:
- Pulling your existing pricing configuration from Stripe (once)
- Making adjustments to the generated configuration file
- Using the Push Model to maintain your pricing going forward
# One-time pull of existing data
npx prices-as-code pull pricing.yml
# Edit pricing.yml as needed...
# From now on, use the push model
npx prices-as-code pricing.yml
Environment Migration
For migrating between environments:
# Pull from production
STRIPE_SECRET_KEY=sk_prod_... npx prices-as-code pull pricing.yml
# Make necessary adjustments for staging...
# Push to staging
STRIPE_SECRET_KEY=sk_staging_... npx prices-as-code pricing.yml
Next Steps
- Learn about the Push Model for ongoing pricing management
- Understand Metadata Usage for enhanced flexibility
- Set up CI/CD Integration for automated pricing updates
- Explore Custom Providers for other payment systems