Think About Event Tracking Before the System Is Already Running
· 68 min read · Views --

Think About Event Tracking Before the System Is Already Running

Author: Alex Xiang


When many systems go live, the team says, “Let’s add some logs first and analyze them later.” A few months later, there are indeed plenty of logs, but the important questions still cannot be answered.

Where did users come from? Unknown. How many times was the registration page opened? Unknown. Why did free users fail to convert? Unknown. When an API suddenly gets more traffic, is it because of new users, crawlers, retry storms, or a customer with a broken integration script? Also unknown.

Logs are not event tracking. Logs are usually for engineers debugging software. They say what happened inside the program. Event tracking is for product, growth, operations, risk control, billing, and engineering together. It says what happened to users and the business.

This article is not about one specific project. It breaks down service event tracking as a general engineering problem: what kinds of services need tracking, what to do at different traffic stages, how to choose a database, how to estimate cost, how to evaluate performance, and how to connect a few real business scenarios from user source to analysis result.

Service event tracking and analytics pipeline

What Event Tracking Solves

The most common misunderstanding is treating event tracking as page-view statistics. Page views and unique visitors matter, but they only tell you how many people came through the door. The more valuable questions are usually sharper:

  • Which acquisition channel brings users who are more likely to register?
  • How long does it take new users to complete their first key action?
  • Where do free users drop off before paying?
  • Which features are usually used before payment?
  • After a release, did the error rate rise in one entry point or across all entries?
  • How do high-value users behave differently from ordinary users?
  • If an API’s usage goes up, did revenue go up too, and did cost stay under control?

These questions do not need just one log line. They require connecting users, sessions, sources, pages, APIs, orders, features, errors, and costs.

So the core of service event tracking is not “record more”. It is building a traceable chain of facts:

User source -> Page visit -> Signup/login -> Activation -> Feature usage -> Cost -> Payment/retention

If this chain is broken, more logs only produce local guesses.

Which Services Need Event Tracking

Not every service needs a complex tracking system on day one. The design should depend on service type, business stage, and traffic scale.

Service typeMost important questionPriority events
Content site, company site, docs siteWhere does traffic come from, and which content drives conversion?page_view, referrer, utm, entry button, signup click
SaaS admin productAre users activated, and which features do they use?login, workspace_created, feature_used, invite_sent
E-commerce or subscription serviceWhere does the funnel leak, and why do payments fail?product_view, checkout_started, payment_succeeded, payment_failed
API platformUsage, success rate, latency, cost, and customer valueapi_call, first_api_call, quota_exceeded, billing_usage
Internal B2B systemAre key workflows completed, and where do approvals or tasks stall?workflow_started, step_completed, approval_rejected
High-traffic gatewayPeaks, anomalies, region distribution, billing, and risk controlrequest_sample, error_bucket, rate_limited, billable_event

Small services should avoid overdesign. A newly launched website does not need a ClickHouse cluster immediately. But it should at least have a stable anonymous_id, page views, key button clicks, and signup success events. Conversely, an API platform with millions of daily calls will soon hurt its business database if it relies only on application logs and ad hoc backend SQL.

Define Events Before Choosing a Database

Database choice matters, but event tracking usually fails first because event definitions are unclear.

A useful event should answer at least four questions:

{
  "event": "api_call",
  "time": "2026-06-29T10:23:45.123Z",
  "user_id": "u_123",
  "anonymous_id": "anon_abc",
  "session_id": "sess_789",
  "source": "web",
  "page": "/pricing",
  "properties": {
    "tool_id": "stock_quote",
    "success": true,
    "latency_ms": 183,
    "credits": 2,
    "plan": "pro"
  }
}

The four questions are:

  • Who: user_id, anonymous_id, account_id, api_key_id
  • When: keep both event time and server receive time if possible
  • Where: page, entry point, client, region, device, service name
  • What: event name and business properties

Two details are especially important.

First, do not lose anonymous users. Many conversions start before signup. Without an anonymous_id, traffic source, landing page, and pricing-page visits before registration cannot be connected to the later user.

Second, keep event names stable. If checkout_start, start_checkout, and click_pay_button are mixed together, dashboards will become messy. Event names should have an allowlist, and event fields should have schema versions.

Collection Options

There are roughly four places to collect events.

Frontend tracking is good for page views, button clicks, form impressions, time on page, and client-side errors. It is closest to the user and can capture referrer, UTM parameters, screen, browser, and entry location. But it is unreliable: the user may close the page, the browser may block requests, the network may fail, and frontend data is easy to forge.

Backend tracking is better for signup success, login success, API key creation, orders, API calls, billing, and permission failures. These events must be trusted from the backend, especially payment and billing. Never trust the frontend to say “payment succeeded.”

Gateway tracking works well for API platforms and microservice entrances: path, status code, latency, tenant, key, rate limiting, circuit breaking, and upstream error. Its advantage is consistency. Its weakness is limited business semantics. A gateway knows that an API was called, but may not know what that call means to the business.

Asynchronous tracking is for high-traffic systems. The main flow only pushes the event into an in-memory queue, local buffer, Kafka, Pulsar, or a cloud queue, while consumers write to storage in batches. This prevents database writes from backpressuring user requests. The tradeoff is system complexity: loss, duplicates, out-of-order events, and replay must be handled.

A common responsibility split looks like this:

Frontend: pages and interactions
Backend: business facts
Gateway: request facts
Queue: buffering and batch writes
Jobs: aggregation, repair, and backfill

End-to-end path from user source to analysis result

Pitfalls During Collection

Service event tracking is not just inserting one row.

Do not write sensitive information into tracking events. Email addresses, phone numbers, tokens, API keys, payment card numbers, raw prompts, and complete query text all require caution. When analysis is needed, record hashes, lengths, categories, or boolean flags instead of secrets and private data.

Do not let tracking block the main path. Signup, payment, and API calls should not fail because event tracking failed. Common approaches are best-effort writes, async queues, timeout-and-drop behavior, and batch writes.

Do not collect extremely granular events with little value. Scroll, mouse move, and hover events can explode volume quickly. Unless you are deliberately building heatmaps, avoid them at first.

Do not store only raw events without aggregation. If every dashboard scans 180 days of detailed rows, the analytics system will become a database stress test. Common metrics should have daily or hourly aggregates, while detail rows are kept for drilldown.

Do not let properties become a garbage bin. JSON fields are flexible, but each event should have a field dictionary. Otherwise, three months later, the same concept may appear as plan, plan_type, tier, and package.

From Single Events to User Journeys

Event analysis usually has several layers.

The simplest layer is counting and trends:

select date_trunc('day', time) as day, count(*) as pv
from event_logs
where event = 'page_view'
group by 1
order by 1;

The second layer is segmentation:

select utm_source, count(distinct anonymous_id) as visitors
from event_logs
where event = 'page_view'
  and time >= now() - interval '7 days'
group by utm_source
order by visitors desc;

The third layer is funnel analysis:

landing_view -> signup_click -> signup_completed -> first_api_call -> payment_succeeded

A funnel should not only show total conversion. Split it by channel, device, country, plan, and entry page. If total conversion drops by 20%, it may be caused by a lower-quality acquisition channel, a broken mobile signup page, or a rising payment failure rate.

The fourth layer is cohort retention. For example: among users who completed their first API call, how many still had calls seven days later? This is closer to product usefulness than DAU alone.

The fifth layer is unit economics. API platforms especially need this layer. A customer may have high usage, but if every call produces third-party cost and revenue does not cover it, that growth is not healthy.

Choosing a Database

Common storage options include PostgreSQL, MongoDB, and ClickHouse. Product analytics tools such as PostHog, Amplitude, and Mixpanel are also options. Building your own gives you control over definitions and makes it easier to connect business data. The cost is that you must own data quality, performance, and operations.

PostgreSQL: The Steadiest Starting Point

If your service already uses PostgreSQL, daily event volume is within a few hundred thousand, and most dashboard queries cover the last 7 or 30 days, PostgreSQL is a good starting point.

Its advantage is easy joins with business data. User, order, credit, workspace, and team tables are often already in the same database or nearby systems. JSONB can also carry event-specific properties. PostgreSQL’s GIN indexes support composite-value queries such as JSONB and full-text search, which makes “structured columns plus JSONB extension” a practical design.

But PostgreSQL is not an infinite event warehouse. When writing an event table:

  • Partition by time, such as monthly or daily partitions
  • Promote frequently queried fields to normal columns instead of putting everything in JSONB
  • Add JSONB GIN indexes sparingly, only when properties really need to be queried
  • Let dashboards query aggregate tables, not raw detail tables
  • Define a detail retention period, such as 90 or 180 days

A steady table design looks like this:

create table event_logs (
  id uuid primary key,
  event text not null,
  event_time timestamptz not null,
  received_at timestamptz not null default now(),
  user_id text,
  anonymous_id text,
  session_id text,
  source text,
  page text,
  referrer text,
  utm_source text,
  utm_campaign text,
  properties jsonb not null default '{}',
  schema_version int not null default 1
) partition by range (event_time);

MongoDB: Usable, But Not Ideal as the Main Analytics Store

MongoDB feels natural for events. Events are JSON-like, fields change often, and writes are simple. MongoDB also has time series collections, where related time and source data can be organized for more efficient time-series storage and queries.

So MongoDB is not impossible for event tracking. It fits these situations:

  • Event structure is unstable and still exploratory
  • The main use is debugging or audit, not complex funnels
  • The team already has mature MongoDB operations
  • Queries are often scoped to one user or object, with fewer full-table aggregations

But if you want to do DAU, channel conversion, retention, payment funnels, user segmentation, and API cost trends for a long time, MongoDB will become harder to use. It is not that complex aggregation pipelines cannot do it, but index count, scan cost, and BI integration cost all rise.

In one sentence: MongoDB can be a flexible event store, but it should not be the core analytics database for event tracking.

ClickHouse: The Right Path for High-Traffic Analytics

ClickHouse is a columnar OLAP database designed for append-only large-scale events, logs, time series, and multi-dimensional aggregation. MergeTree, partitioning, and TTL are core capabilities. ClickHouse documentation also recommends partitioning by the same time field used for TTL so expired data can be dropped by partition rather than deleted row by row.

Its strengths fit event tracking well:

  • Columnar storage reads only the columns needed by a query
  • High compression, especially for repetitive event fields
  • Fast aggregation by time, event, user, channel, and region
  • High batch-write throughput
  • TTL, partitioning, and hot/cold data management support long detail retention

Cloudflare has a representative public case. In a blog post, Cloudflare described using ClickHouse to support HTTP Analytics at millions of requests per second. It has also shared ClickHouse usage in log analytics, customer dashboards, and bot management. These cases show that ClickHouse is not simply “faster PostgreSQL”; it is analytics infrastructure with a different role.

But ClickHouse is not for every stage. It is not good for frequent single-row updates, strong transactions, or replacing the business database. It works best as an analytics database fed asynchronously from PostgreSQL, logs, queues, and services.

Database evolution for different traffic stages

A Simple Selection Table

StageDaily eventsRecommended architectureNotes
Starting1K - 100KPostgreSQL single table or monthly partitionsGet event definitions right first
Growing100K - 500KPostgreSQL partitions + aggregate tablesControl indexes, aggregate early
Fast growth500K - 1MPostgreSQL + ClickHouse sidecar syncStart validating columnar analytics
High traffic1M - 5MClickHouse for detail analytics, PostgreSQL for business factsDashboards should not scan the business database
Very high traffic5M+ClickHouse cluster + queue + tiered storageRequires real data-platform governance

These daily-volume lines are practical heuristics, not absolute thresholds. If events are narrow and queries are simple, PostgreSQL can last longer. If each event has large properties and dashboards scan 180 days frequently, even a few hundred thousand daily events may become painful.

Estimating Cost

Event-tracking cost is mainly determined by five variables:

Daily events × event size × retention period × replica count × query complexity

In PostgreSQL, one event with JSONB, row overhead, and indexes can roughly be estimated at 1KB to 3KB. In ClickHouse, compressed size may be 200B to 800B, depending on field design and repetition.

For 500,000 events per day:

StoragePer-event estimateMonthly detail12-month retention
PostgreSQL2KBAbout 30GBAbout 360GB
PostgreSQL with index expansion4KBAbout 60GBAbout 720GB
ClickHouse compressed500BAbout 7.5GBAbout 90GB

This counts only detail rows. It does not include backups, replicas, aggregate tables, WAL/binlog, or object-storage archives. A safer budget adds a 1.5x to 2x buffer.

For self-hosted ClickHouse, a single node with 4-8 vCPUs, 16-32GB memory, and a few hundred GB to 1TB SSD is often enough for early validation and medium-scale analytics. At millions of daily events or more than one year of detail retention, replicas, backups, hot/cold tiering, and query isolation should be planned seriously.

Evaluating Performance

Do not only benchmark writes. Event systems usually fail when writes, queries, aggregation, and cleanup happen at the same time.

I would watch these metrics:

  • Write latency: whether tracking slows down main business requests
  • Write throughput: events per second, batch size, failed retries
  • Query latency: P50 and P95 of common dashboards
  • Aggregation time: whether daily jobs finish inside their window
  • Storage growth: daily new data and index ratio
  • Data delay: how long after event generation it appears in dashboards
  • Data quality: duplicate rate, loss rate, missing user IDs, invalid event names

A simple acceptance target can be:

MetricSmall/medium service targetHigh-traffic service target
Main-path tracking overheadP95 under 10ms, failures do not affect businessMain path only enqueues, P95 under 3ms
Frontend event visibility delay1-5 minutesWithin 1 minute or near-real-time
Daily aggregation jobFinish within 30 minutesIncremental aggregation in minutes
Common dashboard queryP95 under 2 secondsP95 under 1 second
Detail query windowDefault 7-30 daysLong windows supported by ClickHouse

One easily overlooked point: event growth is not always linear. Normal business growth is one case. A buggy SDK, client retry storm, debug events left on, or crawler traffic is another. The tracking system should be able to degrade gracefully: sample DEBUG events, drop low-priority events, and rate-limit events by user.

Case 1: A Content Site Tracking Signup Conversion

Suppose you run a technical content site. The goal is not just article views, but product registrations.

Event design:

StageEventKey fields
Sourcepage_viewanonymous_id, utm_source, referrer, slug
Readingarticle_readscroll_depth, read_seconds, slug
Clicksignup_clicklocation, slug, button_type
Signupsignup_completeduser_id, anonymous_id, method
Activationfirst_key_actionuser_id, action, hours_since_signup

Analysis path:

Ads/search/social -> Article page -> Signup button -> Signup completed -> First key action

Possible findings:

  • Search traffic has the largest PV, but average signup conversion
  • A deep technical tutorial has modest PV but high conversion
  • Mobile has many signup clicks but few completed signups, indicating a mobile signup issue
  • One channel brings fast signups but low activation, suggesting low-quality traffic

The optimization actions become clear. Instead of “write more articles”, move high-conversion articles forward, fix mobile signup, and adjust acquisition channels.

Case 2: An API Platform Tracking Cost and Revenue

An API platform is dangerous if it only watches call volume. More calls may mean higher cost. If there is no revenue or retention, growth can become loss.

Event design:

StageEventKey fields
Signupsignup_completeduser_id, plan, utm_source
API keyapi_key_createduser_id, key_type
First callfirst_api_calluser_id, tool_id, signup_to_first_call_hours
Callapi_calluser_id, api_key_id, tool_id, success, latency_ms, cost, credits
Quotaquota_exceededuser_id, plan, requested_action
Paymentpayment_succeededuser_id, amount, plan, calls_before_pay

Core analysis:

select
  tool_id,
  count(*) as calls,
  sum((properties->>'cost')::numeric) as cost,
  sum((properties->>'credits')::numeric) as credits,
  avg((properties->>'latency_ms')::numeric) as avg_latency
from event_logs
where event = 'api_call'
  and event_time >= now() - interval '1 day'
group by tool_id
order by calls desc;

This analysis can answer:

  • Which tools are used heavily but do not convert?
  • Which tools have high raw cost and need pricing changes?
  • Is time to first call too long for free users?
  • Is first-call success low because parameters are hard, docs are unclear, or third-party providers are unstable?

For an API platform, “request facts” and “business behavior” should be separated. Request facts can come from gateway or backend and must be accurate. Product events explain why users reached that point.

Case 3: A Subscription Service Tracking the Payment Funnel

Subscription services should not only watch successful payments. The path before payment is more important.

Event chain:

pricing_view -> plan_select -> checkout_started -> payment_succeeded/payment_failed -> subscription_renewed/subscription_cancelled

Key fields:

  • current_plan
  • selected_plan
  • price
  • payment_method
  • failure_reason
  • country
  • device_type
  • entry_point

Do not calculate only one total funnel. Split by:

  • Mobile and desktop
  • Country or region
  • Entry point, such as home page, docs, or usage-limit reminder
  • New users and returning users
  • Monthly and annual plans

A common finding is that plan_select -> checkout_started converts well, but checkout_started -> payment_succeeded performs poorly. The problem is often not the pricing page, but the payment path: unsupported payment method, failed 3DS verification, excessive billing-address requirements, or unclear error messages.

Evolution Strategy

I prefer a four-step evolution.

First, collect only core events: page view, signup success, login success, key feature usage, payment success, and API call. Get definitions correct before chasing event count.

Second, complete the identity chain. Anonymous user, logged-in user, account, team, and API key should connect. Without identity, funnel and retention analysis are unstable.

Third, build aggregate tables and dashboards: DAU, signup conversion, first key action, payment conversion, feature usage, call success rate, and cost trend. Business users should not need engineers to run SQL every day.

Fourth, introduce an analytics database. When PostgreSQL can no longer handle long-window detail scans, synchronize events to ClickHouse. By then, event definitions are stable and table design is easier to get right.

A healthy tracking system should start simple but grow smoothly:

PostgreSQL raw events
  -> PostgreSQL partitions + aggregate tables
  -> PostgreSQL + ClickHouse sidecar analytics
  -> ClickHouse for detail analytics, PostgreSQL for business facts

Event Tracking Is an Agreement Between Product and Engineering

Service event tracking is not a product manager writing an event spreadsheet, nor an engineer adding a few log lines. It is closer to an agreement: how we define user behavior, success, cost, and one truly valuable use.

It does not need to be heavy at the start. For a small service, ten accurate core events are more useful than one hundred chaotic events. When traffic grows, queues, partitions, ClickHouse, and storage tiering can come later.

What really matters is that after the system goes live, the team can keep answering these questions:

  • Where did users come from?
  • What did they do?
  • Where did they get stuck?
  • Which behaviors generated revenue?
  • Which calls consumed cost?
  • After a change, did the result become better or worse?

If the system can answer these questions, event tracking has started to create real value.

References