The Two Ways Usage-Based Pricing Goes Wrong
Every usage-priced analytics product eventually faces the same question: what happens when a customer blows past their allowance? The industry has settled on two answers, and both punish the customer.
Fail closed: the vendor stops collecting. Your best month of the year -- a launch, a press hit, a viral post -- is exactly when your analytics goes dark. The traffic spike that mattered most is the one you can't see.
Auto-bill: the vendor keeps collecting and sends you an invoice you never agreed to. The spike still costs you; you just find out at the end of the month.
We built ClickStream's billing around a third answer: paid tiers fail open, and overage billing is opt-in. When a paid account exceeds its included pageview allowance, ingestion continues exactly as before. The collector marks its responses with over_limit_fail_open billing metadata -- an internal flag, not a behavior change -- and your dashboard, your tracking, and your site carry on. Nothing is throttled, nothing is dropped, nothing breaks.
A billing limit is an accounting fact. It should never become an engineering event on your website.
Overage Is Opt-In, Not a Trap
Fail-open collection would be a hollow promise if it silently metered everything and billed you later. So the other half of the design is just as deliberate: metered overage billing runs only for accounts that explicitly enable it.
This is enforced at the checkout level, not just in policy. When you subscribe to Growth, Scale, or Network, the checkout contains exactly one visible line item: the flat plan price. No pageview meter, no coverage meter, no per-site meter is attached to your subscription at purchase. Those metered items are added only when you explicitly turn on auto-billed overages, add a billable extra site, or enable the optional enrichment add-on.
If you never opt in, exceeding your allowance costs you nothing that month. Your usage page shows you're over, and the honest next conversation is an upgrade -- on your schedule, not via a surprise invoice.
When you do opt in, the rates are published, not negotiated:
| Overage meter | Unit | Growth | Scale | Network |
|---|---|---|---|---|
| Human pageviews | per 100,000 | $2.00 | $1.00 | $0.50 |
| Signals Coverage | per 1,000,000 events | $5.00 | $3.00 | $2.00 |
The same opt-in philosophy applies to add-ons. Optional Visitor Enrichment -- the one feature that calls a third-party data vendor -- is off by default, separately billed at $97 per site per month with 10,000 included checks and $10 per additional 1,000, and it never turns itself on.
The One Hard Stop, and Why It's Fair
There is exactly one place ClickStream will stop ingesting: the free Hobby tier, and only at 3x its included allowance. Hobby includes 50,000 human pageviews per month; collection hard-stops at 150,000, when the collector begins returning HTTP 429 usage_limit_exceeded (with a Retry-After header) until the billing period resets or you upgrade.
The reasoning is simple economics: an unpaid account with no payment method has no overage path, so unpaid traffic can't be allowed to run uncapped infrastructure cost forever. But note what a 3x threshold means in practice -- a free account gets to double its allowance and then some before anything changes, and even then, the failure is contained to tracking. The script tag loads asynchronously and a rejected collection request is invisible to your visitors. Your pages keep rendering; only the data collection pauses. A billing state never breaks a free site either -- it just stops the meter.
Hobby remains a real tier, not a demo: one site, no credit card at signup, basic Signals snapshots, and a live-session peek. The 3x buffer exists so a traffic spike on a free site is a growth story, not an outage.
You're Billed for Humans, Not Bots
The second trust decision sits underneath the first: what counts as usage? ClickStream bills on human pageviews -- not raw events, not requests. Clicks, scrolls, and custom events don't multiply your bill, and neither does the growing share of your traffic that isn't human at all.
ClickStream's detection layer classifies traffic across 11 bot categories, drawing on a registry of 158 named bots -- including 38 named AI agents such as GPTBot, ClaudeBot, and PerplexityBot. On a per-event billing model, all of that classification work would eat your quota: you'd literally pay to find out you were being crawled. Instead, bot, AI-crawler, answer-engine, kiosk, and tool traffic draws on a separate meter called Signals Coverage, set at 5x your pageview allowance on every tier:
| Tier | Human pageviews / mo | Signals Coverage / mo |
|---|---|---|
| Hobby | 50,000 | 250,000 events |
| Growth | 500,000 | 2,500,000 events |
| Scale | 5,000,000 | 25,000,000 events |
| Network | 25,000,000 | 250,000,000 events |
Why meter it at all? Because non-human traffic still creates real compute -- edge requests, CPU, storage, and the active Signals API reads your own code makes. Signals Coverage exists to keep that cost honest without ever letting a crawler swarm inflate the number you're actually billed on. Human pageviews are never double-counted in Signals Coverage.
And when an account exhausts its coverage budget without paid overage? Same principle as everywhere else: sites fail open through cached, sampled, aggregate, or default classifications. Your site keeps working; classification degrades gracefully instead of erroring.
The API Fails Open Too
Fail-open thinking extends into the client library your page code calls. The Signals SDK (@clickstreamhq/signals, currently a developer preview at 0.1.0-alpha) is designed so that a missing, delayed, or budget-exhausted snapshot can never take your page down with it:
getVisitorOrNull()resolves tonullinstead of throwing when no snapshot is available -- render first, personalize second.- If the API rate-limits a read with a 429, the client reuses its last cached snapshot rather than failing.
- When Signals Coverage is exhausted, the client surfaces placeholder snapshots flagged with
coverageMode: 'degraded'-- so you can see you're degraded -- and those placeholders are built to fail personalization gates closed: helpers likeisHighIntent()returnfalserather than guessing, while the page renders normally.
Collection fails open; personalization decisions fail safe. In practice that looks like this:
import { configure, getVisitorOrNull, isBot, isHighIntent } from '@clickstreamhq/signals';
// configure() must run before any visitor read
configure({ apiKey: 'cs_live_your_key' });
// Resolves to null instead of throwing when no snapshot
// is available -- your page renders either way.
const visitor = await getVisitorOrNull();
if (visitor && !isBot(visitor) && isHighIntent(visitor)) {
// visitor.scores.intent >= 70 -- safe to show the high-intent CTA
showDemoBanner();
}
If the snapshot never arrives -- network issue, coverage exhausted, brand-new visitor -- visitor is null, the condition is false, and the page simply ships its default experience. No error boundary required, no blank hero while a personalization call times out.
The same posture runs server-side. Every one of the behavioral scoring models executes inside an isolation wrapper at the edge: if a model crashes on a weird event, it degrades to defaults and event ingestion is never delayed. Even account suspension is engineered politely -- a suspended account's script URL serves a silent one-line comment, not console errors or a broken tag.
The Numbers, Published
Trust in billing is mostly a function of whether the vendor will write the numbers down. Here are ours -- the same quotas the billing system enforces:
| Tier | Monthly | Annual | Identity resolutions / mo | Included seats | Session replay retention |
|---|---|---|---|---|---|
| Hobby | $0 | $0 | -- | -- | 1-hour peek (50 sessions) |
| Growth | $199 | $1,791 | 1,000 | 3 | 7 days |
| Scale | $499 | $4,491 | 10,000 | 10 | 30 days |
| Network | $1,499 | $13,491 | 50,000 | 25 | 90 days |
| Enterprise | Contract | Contract | Contract | Contract | Contract |
A few details worth calling out:
- Annual billing is 9x the monthly price -- three months free. Growth works out to $1,791 a year against $2,388 paid monthly; Scale $4,491 against $5,988; Network $13,491 against $17,988.
- Viewers are always free. Seat counts above are editing seats; read-only teammates never consume one. Extra seats are $29/month each.
- Identity resolution unlocks at Growth, with the included monthly quotas above -- and so do all behavioral scoring models. Realtime Signals unlocks at Scale.
- Rate limits are abuse protection, not billing. The collector sustains 100 / 1,000 / 5,000 / 25,000 requests per second per API key across the four self-serve tiers. Those ceilings exist to stop abuse; the meter that determines your bill is human pageviews, full stop.
The Bottom Line
Analytics pricing is a trust exercise, because the vendor controls both the meter and the consequences of the meter. Our position is that the consequences should always land on the bill, never on your website:
- Paid tiers fail open -- exceeding your allowance never drops tracking or breaks your site
- Overage billing is opt-in -- metered charges exist only if you enable them; checkout is one flat line item
- The free tier hard-stops only at 3x its allowance -- and even then, only collection pauses
- You're billed on human pageviews -- bot and AI traffic draws on a separate Signals Coverage meter at 5x your allowance
- The client fails safe --
getVisitorOrNull(), cached-snapshot reuse, and degraded-mode placeholders keep pages rendering - The quotas are published -- prices, resolutions, seats, and replay retention are the same numbers the billing code enforces
Fail-open billing is a one-way promise: when something has to give, it's our invoice logic that bends -- not your website.