What you actually get when you pay for an event

Contents

When you pay for an event in PostHog, you pay for more than a row in a database. The price covers the work to collect that event, keep it safe, make it useful, store it for many years, query it as often as you like, and send it to other tools. It also buys peace of mind: the pipeline is built so your data arrives complete and correct, and when something breaks, our engineers get paged, not yours.

This page explains each of those jobs, so you know what the price includes. It's also useful if you're thinking about building your own pipeline, for example on ClickHouse. AI agents make the first version much faster to build than it used to be, so that's a fair option to consider. This page helps you compare the two like with like.

You don't need to be an engineer to follow it. It helps, but every section starts in plain English and ends with the technical detail so it can help users at all levels.

No bill yet? Every PostHog product has a free tier, and they're big enough that 97% of users never pay us a penny. If you're inside the free tier, your events cost nothing.

The price

An event is one thing that happens in your product: someone views a page, clicks a button, signs up, or pays you. Product Analytics bills per event. The first 1 million events each month are free, and the price per event drops as you send more. Below are the live rates for anonymous events, which don't carry a person profile.

1,000,000
events/month

$0

1M10M50M

Identified events add a person profile charge on top, because person processing is the most expensive step in our pipeline. The pricing page has the full tables for both.

Those are the only line items for events. We don't charge to store them, to query them in PostHog, or per seat, so you can run as much analysis as you like with as many colleagues as you like.

What happens to one event

Every analytics setup, bought or built, has the same job.

  • You have to get data in from your product, and often from other tools too.
  • You have to keep it safe for as long as anyone might need it, and nobody knows when that'll be.
  • You have to keep it available for when you want to use it, or send it off wherever you want it to go.

That sounds like three jobs. In practice it's six, and each one has its own ways it can go wrong.

Step 1: Getting it in

Say you ship a mobile app. Someone opens it on a train, taps through a few screens, loses signal, and closes it. Those taps still need to reach you once the phone is back online, in the right order and with the right time on them. Meanwhile your website has a different problem: some of your visitors run ad blockers that strip out tracking scripts. Finally, your backend records the events that matter most, like signups and payments, straight from your servers.

It's rarely just your product, either. Sooner or later someone wants Stripe payments or HubSpot deals next to product usage, so they can see which features your paying customers actually use. So you need to pull in data from those places too, maintain the pipeline, and handle the associated costs.

How it works at PostHog: Our SDKs batch, compress, and retry. The capture service decompresses the payload, validates it, and corrects the timestamp using the time your client says it sent the batch, so a phone that was offline for an hour still lands its events in the right minute. It also adds a UUID if the SDK didn't.

If capture can't write to the queue, it returns an error and the SDK tries again, so a short outage on our side doesn't lose your data. Finally, a reverse proxy lets you send events from your own domain, past ad blockers.

For data from other tools, sources sync Stripe, HubSpot, Postgres, S3, and more on a schedule, so you can query them next to your events with SQL. Synced rows have their own free tier and bill per row, separately from events.

Without it, events from a phone with the wrong clock land on the wrong day, retries count twice, and ad blockers quietly create a blind spot in your data.

Step 2: Not losing it

Data, like taxes, has a habit of arriving all at once. You hit the front page of Hacker News, a spam bot finds your signup form, or a buggy release fires the same event in a loop. Meanwhile, the database at the end of the line needs a restart now and then for upgrades. None of that should lose you data, but any of them could.

How it works at PostHog: Every event goes into Kafka before anything else touches it, and capture doesn't reply to your SDK until Kafka has acknowledged the write on every in-sync replica. The queue absorbs launch-day spikes and bots, and waits out database outages. Events from the same user stay in order.

If a single ID sends more than about 5,000 events a minute, it moves to an overflow lane so it can't slow anyone else down. Nothing gets dropped, but while that ID is in the overflow lane, its events can process out of order and skip person profile creation and updates. You'll get an ingestion warning when it happens.

If an ingestion worker crashes halfway through a batch, Kafka redelivers it. Anything we can't process goes to a dead letter queue instead of disappearing.

Without it, a traffic spike or a database restart can mean you lose your precious data for good.

Step 3: Making it mean something

Raw events are messy. Your iOS app sends Signed Up, your web app sends signup_completed, and last week's release misspelled a property name. Someone reads your blog on their phone at lunch and signs up on their laptop that evening, and as far as the raw data knows, that's two strangers. Before anyone can trust a chart, the data needs checking and joining up.

How it works at PostHog: Ingestion validates each event, drops anything older than a limit you set, and runs your transformations. It adds country and city from GeoIP, gives cookieless events a daily-rotating hash instead of a cookie, and attaches UTM and referrer data to the session. Every event and property name goes into a catalog, which is how the UI, SQL autocomplete, and PostHog AI know what exists. If something's wrong with an event, an ingestion warning tells you which one. When two names mean the same thing, you can combine them into one action or rename one with a transformation.

Identified events also go through identity resolution. We create the person, merge their anonymous history when they identify, and update their properties in order. That's what the person profile charge pays for, and it's the hardest part to build yourself. Until something merges the phone and the laptop, every funnel that crosses signup is wrong.

Without it, one platform renames a property, one metric quietly splits in two, and nobody notices until your next shareholder meeting.

Step 4: Storing it for years

Simply put: you don't know which questions you'll need to ask next year. Your board wants to see how this year's signups compare with your first cohort. A new PM wants to know whether the redesign two years ago actually worked. You can only answer those sorts of questions if the data from back then is still there and still fast to query.

How it works at PostHog: Events land in a sharded, replicated ClickHouse cluster, with properties compressed using ZSTD. Hot data (that which you use regularly) sits on local NVMe and moves to cheaper tiers as it ages. Every week we look at slow queries and materialize the columns that would make them fast.

We're also rebuilding the storage format so each property is stored once, with its real type, which makes common queries up to 2x faster. GDPR deletions run as batched jobs, because deleting anything from ClickHouse means rewriting whole partitions.

Paid plans keep events for many years and free plans for one. You can set a shorter window if you need it, however.

Without all this, a database that keeps only one copy of your data can lose it when a disk fails, and queries get slower as the data grows – a problem that's small when you're handling a few thousand events for your hobby project, but colossal when you're handling millions and billions of events for your business.

Step 5: Querying it as often as you like

Data is only worth keeping if people actually use it. Your PM builds a funnel for the new checkout. Your CEO opens the same dashboard every Monday morning. An engineer writes SQL to chase a bug, and someone in customer success asks PostHog AI which accounts stopped using a feature last week. They're all reading the same events at the same time, and none of them should have to wait for the others.

(Well, maybe the PM.)

How it works at PostHog: Funnels, retention, paths, lifecycle, dashboards, SQL, and PostHog AI all run on the same events, and the compute for those queries is in the event price.

We run guard rails so one query can't take a cluster down. A query gets 60 seconds by default and 10 minutes in the background, and each organization has a concurrency limit. Inside those limits, we don't meter queries.

Step 6: Getting it out

Sometimes the data needs to go somewhere else entirely. Your data team wants it in Snowflake next to everything else the company tracks. Your sales team wants a Slack message when a big account signs up, or a HubSpot contact updated when someone upgrades. And if you ever leave PostHog, you want every event to come with you.

How it works at PostHog: Batch exports can send events to S3, Snowflake, BigQuery, Postgres, Redshift, Databricks, or Azure as JSON or Parquet, on a schedule you set. The first 1 million rows you export each month are free. After that, exports bill per row under Data Pipelines pricing, not the event price.

Destinations send events to tools like Slack, HubSpot, and Customer.io as they happen. They have their own free tier and bill separately from events too. The query API returns anything SQL can express. If you leave, your data leaves with you.

Without it, every tool that wants your data needs its own export job, and each one needs its own upkeep.

If you build it yourself

Every one of those jobs still exists when you run the pipeline yourself. This table shows what each one looks like on both sides. The second column is what we run for you, the third is what you'd run instead, and the last is when the job needs time from your team.

It assumes your build runs in production for the long term, and that someone on your team owns it.

JobWhat PostHog runsWhat you run insteadWhen it needs your team
Getting it inSDKs for web, iOS, Android, React Native, Flutter, and server SDKs in Node, Python, Go, Java, Ruby, PHP, .NET, and more. A public capture endpoint. Sources that sync Stripe, HubSpot, and databases.An SDK for every platform you ship on. An endpoint on the public internet. A sync job for every other tool your team wants data from.When a mobile release changes how events are sent
Not losing itKafka with replication, overflow lanes, a dead letter queue, and replay after a crashA queue in front of the database, or direct inserts with their own retry logicWhen traffic spikes or the database restarts
Making it mean somethingValidation, GeoIP, cookieless hashing, session attribution, a definitions catalog, and warningsA transform step for every rule, plus a catalog of event and property namesWhen one platform renames a property
Knowing who did itPerson profiles, anonymous-to-identified merges, and property updates in orderAn identity table, merge logic that copes with two devices identifying at once, and backfills when it gets it wrongWhen one customer shows up as two
Storing itSharding, replication, tiering, compression, materialized columns, backups, and GDPR deletesClickHouse operations, upgrades validated against your real queries, and backups with tested restoresWhen an upgrade changes a query result
Querying itInsights, SQL, AI, caching, and per-organization limitsA dashboard or BI tool, plus limits so one query can't slow down everyone else'sWhen one large query slows down the cluster
Getting it outBatch exports, real-time destinations, and the query APIAn export job or a webhook for every tool that wants the dataWhen an export job stops

Costs that arrive later

A build estimate from an agent usually covers the first version of the system: the servers, the storage, and the setup. The costs below arrive later, so estimates often leave them out, whether a person or an agent writes them.

Storage for years, not months

Storage looks cheap in month one, because there's only one month of it. Paid plans keep events for many years, so a fair comparison costs the same window. Your storage bill grows every month: in month 12 you're paying to store 12 months of events, and in month 48 you're paying for 48. The ledger below works out what that adds up to at your volume, your cloud's price per GB-month, and at least two replicas.

Compute for as long as you keep the data

Every event gets read over and over. Each dashboard refresh, funnel, cohort recalculation, and SQL query reads it again, and all of that is in the price. Asking PostHog AI spends AI credits on top, but the queries it runs are covered.

Remember the CEO's Monday morning dashboard? Now picture the whole company opening theirs at the same time. A cluster you run has to be big enough for that moment. For the rest of the week it mostly sits idle, and it bills by the hour the whole time.

Scaling you didn't plan for

Traffic doesn't grow in a straight line. A launch, a bot, an SDK stuck in a retry loop, or an acquisition can multiply your event volume in a day. Our pipeline absorbs that with Kafka, overflow lanes, and clusters sized for our whole customer base. A cluster you run needs room for those days too, or a plan for when it runs out.

Time you don't spend on your product

Every hour someone spends upgrading ClickHouse or fixing an SDK is an hour not spent on the thing your customers pay you for. The ledger counts those hours at a loaded rate. At an early-stage company, the bigger cost can be a feature that ships later because an engineer was busy with the pipeline.

The features you'll be asked for next

Your first build gives you an events table and a dashboard. A week later, someone asks for a funnel. Then retention, then cohorts, then a way to target a feature flag at one of those cohorts. Every request is reasonable, and every one is another system to build and maintain.

This adds a lot of work and scope over time. You can trust us on that.

In PostHog, the same events already power feature flag targeting, experiment metrics, and the filters in Session Replay. You pay for an event once, and every product can use it. An event store you build talks to nothing until you write the connection yourself. Our post on building your own feature flags covers the same trade-off.

Trust

Data is only useful if people believe it. A wrong number costs more than the time it takes to fix, because of the decisions people made with it first. You want to be able to put the numbers in front of a board or an investor without an asterisk. We have SOC 2, HIPAA, and GDPR controls, and a public status page. When we lost Logs data in February 2026, we published what happened and what we changed. If you build your own, those controls and that reporting become your team's job too.

Your own ledger

This is where you do the math. You'll want an engineer for the technical rows, like bytes per event and compute nodes, but anyone can fill in the rest.

Fill this in with your numbers. If an agent is helping with your estimate, ask it to fill this in too and say where each number came from.

InputYour numberNotes
Events per monthYour billing page shows it
Compressed bytes per eventMeasure it on a sample of your real events in ClickHouse
ReplicasAt least 2, or a disk failure is data loss
Months retainedHow far back you need to query. Paid plans keep many years
Storage price per GB-monthYour cloud's list price for the tier you use
Compute nodes × hourly priceIngestion and query nodes, 730 hours a month
QueueManaged Kafka or equivalent
Engineer hours per monthUpgrades, schema changes, backups, SDK maintenance
On-callWho, and what it costs them

In plain English, work out how much data you'll store by a given month and what that costs. Add the servers and the people, then divide by the number of events you send. As a formula:

GB stored at month N = events × bytes × replicas × min(N, months retained) ÷ 1,000,000,000
storage at month N = GB stored × price per GB-month
monthly total = storage + compute + queue + (engineer hours × loaded rate) + on-call
your cost per event = monthly total ÷ events per month

Compare the last line to a PostHog bill at the same volume. Take the monthly total from the pricing calculator, with any add-ons you need, and divide it by your monthly events. The free million and the falling tiers mean that average comes out lower than the rates at the top of this page. Run it for month 1, then again for month 36. If an agent is doing the math, point it at our pricing guide for agents for the PostHog side.

The ledger only counts the costs you can put a price on. It leaves out trust, correct data, time away from your product, and the features you'll be asked to build next. Those are real costs too, so weigh them when you compare the two totals.

When building is the right call

Building your own pipeline is the better choice for some teams. These are the cases where we'd build it too.

You sell analytics infrastructure. The pipeline is your product, so the engineering time is the business, not overhead.

You already run ClickHouse for something else, and a data team treats it like a product, with on-call, upgrades, and tested backups. Adding an events table to a cluster you already operate is a very different decision from standing one up.

Your data doesn't fit an events table, like wide logs, sensor-rate time series, or rows you need to update in place. Our pipeline is built for append-only events, so a different tool may suit you better.

If you're not sure which side you're on, fill in the ledger. It gives you a better answer than any general rule.

How to lower your PostHog bill

If you want to keep using PostHog but pay less, these changes help most.

  • Capture fewer events in total. Autocapture noise and an identify() call on every page are the two we see most.

  • Send anonymous events where you don't need person data. Marketing site traffic and backend events rarely do.

  • Set a billing limit so you know the most you'll pay in a month.

If you'd like help with your setup, talk to us.

Still have questions?

Was this page useful?