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:

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:

  1. Pulling your existing pricing configuration from Stripe (once)
  2. Making adjustments to the generated configuration file
  3. 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