Team / seat billing
Per-seat billing means the subscription quantity tracks how many people are on a team. ShipVeryFast ships a teams feature flag (off by default) as a placeholder. This recipe outlines the build on top of the existing billing model.
Model teams and membership
Add teams and team_members tables. A user belongs to a team with a role (owner, admin, member). Bill the team, not the user.
create table public.teams (
id uuid primary key default gen_random_uuid(),
name text not null,
stripe_subscription_id text
);
create table public.team_members (
team_id uuid references public.teams(id),
user_id uuid references public.users(id),
role text not null default 'member',
primary key (team_id, user_id)
);Use a quantity-based price
Create a per-seat price in Stripe. The subscription quantity is the seat count, so the checkout you already have just sets a quantity.
Sync seats
When you add or remove a member, update the Stripe subscription quantity. The existing webhook keeps the stored status in step, so access checks stay unchanged.
Build on the billing model
The rule from the billing model still holds: the webhook is the source of truth. Seat changes flow through Stripe and back into your database.
