---
name: stripe-infra-cost-per-customer
description: "On the 3rd of each month: last month's AWS, Vercel, Cloudflare and Supabase bills divided by paying Stripe customers, and what that did to margin. Use when the user asks for this, or when it runs on a schedule."
---

# Infrastructure cost per paying customer: cloud bills and Stripe

On the 3rd of each month: last month's AWS, Vercel, Cloudflare and Supabase bills divided by paying Stripe customers, and what that did to margin.

Cloud bills grow in steps nobody notices: a bigger database instance, a log retention setting, a new region. Each bill looks reasonable on its own, and revenue grows too, so the only number that tells you whether the business is getting cheaper or dearer to run is the ratio, and nobody keeps it.

On the 3rd of each month the agent adds up last month's hosting from whichever providers you use, counts paying customers in Stripe as of month end, and divides. It sets the result against MRR for an infrastructure margin and against last month's card, and when the cost per customer jumps it names the provider and service behind it.

## Two ways to get the data

Use the API or MCP route when you have an MCP server, a CLI or an API token for the app. Otherwise, if you can drive a browser the user is signed in to (Claude in Chrome, a Playwright or Chrome DevTools MCP server), use the browser route. Say which one you used.

## Route A: API or MCP server

### What you need

- Read-only billing access for each provider you use: an AWS role with `ce:GetCostAndUsage`, a Vercel token on a team role that can read billing (Owner, Billing or Enterprise Viewer, among others), a Cloudflare token with billing read.
- A Stripe restricted key with Read on Subscriptions, and Supabase's monthly amount in the settings if you host there.

If something is missing, say what and stop; do not invent numbers.

### Steps

1. **Total last month's AWS bill** (AWS): Run `aws ce get-cost-and-usage --time-period Start=<first of last month>,End=<first of this month> --granularity MONTHLY --metrics UnblendedCost --group-by Type=DIMENSION,Key=RECORD_TYPE` (the end date is exclusive). Add every record type except `Credit` and `Refund`, and list credits on their own line: startup credits hide the real cost until they run out.
2. **Add the other providers, whichever you use** (Vercel): Vercel: `GET /v1/billing/charges?teamId=<team>&from=<start>&to=<end>` streams FOCUS rows; sum `BilledCost` and skip `ChargeCategory` `Credit`. Cloudflare: `GET /accounts/{account_id}/billing/history` and sum `amount` for items whose `occurred_at` falls in the month. Supabase's Management API has no invoice endpoint, so use the monthly amount set in the skill's settings or the invoice total read from the Billing page.
3. **Count paying customers at month end** (Stripe): List `GET /v1/subscriptions?status=active` and keep subscriptions whose monthly amount after discounts is above zero. Rewind to the last day of the month: drop ones `created` after it, and add back `status=canceled` subscriptions whose `canceled_at` is after it. Count distinct `customer` values and sum the normalized monthly amounts for MRR.
4. **Divide and compare with last month**: Cost per paying customer = total infrastructure / paying customers. Infrastructure margin = (MRR - infrastructure) / MRR; payment fees and support are not in it, and the card says so. Read last month's ratio and margin from `GET https://briefkin.dev/v1/cards/insight-stripe-infra-cost-per-customer`. Alert when cost per customer rose 15% or more, or margin fell 2 points or more.
5. **Name the service behind a jump** (AWS): On an alert, rerun Cost Explorer for both months grouped by `SERVICE`, and Vercel charges by `ServiceName`, and list the 3 largest increases in dollars next to the change in customers, so "cost grew 42%, customers 3%" points at a line item.

## Route B: the browser

### What you need

- Signed in to the AWS console with billing access, Vercel as a team member who can see billing, Cloudflare and Supabase with billing access, and Stripe with a role that can view subscriptions.

If something is missing, say what and stop; do not invent numbers.

### Steps

Start at https://console.aws.amazon.com/billing/home#/bills. The user is signed in already; never type passwords or codes, and ask if a sign-in page appears.

1. **Read the AWS bill**: On Bills, choose last month in the billing period picker and read the total. Note any Credits line separately and add it back, so a startup credit does not hide the real cost; the Charges by service list shows which services grew.
2. **Read Vercel, Cloudflare and Supabase**: Vercel: team Settings > Billing, read last month's invoice. Cloudflare: Manage Account > Billing > Billing History, add last month's charges. Supabase: the organization's Billing page, Invoices, last month's total. Skip any you do not use.
3. **Count paying customers in Stripe**: Open `https://dashboard.stripe.com/subscriptions`, filter Status `Active` and read the count, leaving out $0 and fully discounted plans. Billing > Overview shows MRR on the same screen; read it for the margin.
4. **Divide and compare**: Cost per paying customer is total infrastructure divided by that count; infrastructure margin is (MRR - infrastructure) / MRR. Compare with the same numbers for the month before, and flag a rise of 15% or more or a margin drop of 2 points or more.

Note: Stripe's subscription list counts customers today, not at month end, so run this early in the month. The dashboard MRR figure can differ slightly from a hand count because of how Stripe treats discounts and tax. Vercel and Cloudflare invoices may straddle the month by a few days.

## The report

- **Infrastructure cost per paying customer** last month, with the monthly trend.
- **Infrastructure margin** against MRR, this month and last.
- **Spend by provider** for both months, and credits used.
- **Paying customers** at month end and the change.
- On a jump, the 3 services that grew most, and one line on what to look at first, for example "RDS doubled after the instance resize on the 8th: check whether the larger class is still needed".

## Post it to Briefkin

When `BRIEFKIN_TOKEN` is set, or `~/.config/briefkin/env` exists (the installer from https://briefkin.dev/docs writes it), also send the result to the user's Briefkin board as one card. Keep the `item_key` the same on every run so the card updates in place, use a new `event_id` per run, and put today's real numbers in place of the example ones. If the request fails, say so once and carry on.

```bash
[ -n "${BRIEFKIN_TOKEN:-}" ] || . ~/.config/briefkin/env
curl -sS -X POST "${BRIEFKIN_URL:-https://briefkin.dev}/v1/events" \
  -H "authorization: Bearer $BRIEFKIN_TOKEN" \
  -H "content-type: application/json" \
  -d @- <<'JSON'
{
  "v": 1,
  "event_id": "stripe-infra-cost-per-customer/<date of this run, e.g. 2026-10-16>",
  "item_key": "stripe-infra-cost-per-customer",
  "project": "acme-web",
  "source": "Infrastructure cost per paying customer: cloud bills and Stripe skill",
  "kind": "metric",
  "title": "Infra cost per customer up 38%, margin down to 88%",
  "metric": {
    "label": "Infra cost per paying customer",
    "value": 0.84,
    "prefix": "$",
    "period_label": "Last month",
    "better": "lower",
    "period_start": "<start of the period, ISO 8601>",
    "period_end": "<end of the period, ISO 8601>"
  },
  "glance": [
    {
      "type": "Grid",
      "props": {
        "columns": 3
      },
      "children": [
        {
          "type": "Stat",
          "props": {
            "label": "Infra margin",
            "value": 88,
            "unit": "%",
            "delta": -3
          }
        },
        {
          "type": "Stat",
          "props": {
            "label": "Infra spend",
            "value": "$1,596",
            "delta": 42,
            "better": "lower"
          }
        },
        {
          "type": "Stat",
          "props": {
            "label": "Paying customers",
            "value": 1900,
            "delta": 3
          }
        }
      ]
    }
  ],
  "widget": [
    {
      "type": "Table",
      "props": {
        "columns": [
          "Provider",
          "Last month",
          "Month before",
          "Change"
        ],
        "align": [
          "left",
          "right",
          "right",
          "right"
        ],
        "rows": [
          [
            "AWS",
            "$1,020",
            "$640",
            "+59%"
          ],
          [
            "Vercel",
            "$312",
            "$240",
            "+30%"
          ],
          [
            "Supabase",
            "$189",
            "$167",
            "+13%"
          ],
          [
            "Cloudflare",
            "$75",
            "$75",
            "0%"
          ],
          [
            "Total",
            "$1,596",
            "$1,122",
            "+42%"
          ]
        ]
      }
    },
    {
      "type": "Callout",
      "props": {
        "text": "Most of the rise is AWS: Amazon Relational Database Service went from $210 to $480 and EC2 data transfer added $90. Margin here is MRR ($13,300) minus infrastructure only.",
        "tone": "warn"
      }
    }
  ],
  "size": "md"
}
JSON
```

Widgets come from the Briefkin catalog (https://briefkin.dev/v1/catalog). Without a token, just give the user the report.

Set `period_start` and `period_end` to the window the number covers: the tile names it from them ("Last 7 days", "Today", "This month"). For a count right now (open items, a balance), send `"period_label": ""` so no period shows; for another name, send it as `period_label` (at most 24 characters).

## Run it on a schedule

Suggested: 3rd of the month at 9:00 (`0 9 3 * *`). From cron, with the agent signed in on that machine:

```bash
0 9 3 * * claude -p "Run the stripe-infra-cost-per-customer skill"
# Codex: codex exec, Gemini CLI: gemini -p, Copilot CLI: copilot -p, OpenCode: opencode run
```

Or use the agent's own scheduler (Claude Code routines, Codex automations, Claude or ChatGPT scheduled tasks): https://briefkin.dev/skills/stripe-infra-cost-per-customer#schedule

Source: https://briefkin.dev/skills/stripe-infra-cost-per-customer
