The bad release in my test introduced one new bug: a payment gateway error that fired on every fifth card charge. PostHog turned it into two issues, and TrackJS turned three failed charges into three separate errors, plus a fourth copy from the browser. The two tools group errors in opposite ways, and on this release each way broke down.
TrackJS groups by the error message, and the charge amount was part of the message. PostHog groups by the stack trace, which ignores the amount. On Node, though, PostHog also counted the runtime's internal frames, and the slow database query in that release changed them. Which of these failure modes you'd rather live with says a lot about which tool fits your team.
PostHog is a product platform where error tracking is one product among many, sharing a project and its user data with session replay, logs, tracing, metrics and analytics. An error in PostHog can open the session recording, the server trace and the logs that go with it.
TrackJS keeps to one job. TrackJS is a browser-first JavaScript error monitor, paired with a lighter agent for Node.js and an AI Debugger on every error, and its bill is set by page views. Each error carries a telemetry timeline of the clicks, requests, navigations and console lines that came before it.
I ran both against the same intentionally broken test bookstore in late October 2026. You'll see them compared on setup, browser and server errors, source maps, debugging, the path from browser to server, grouping, replay, releases and regressions, performance, logs, alerts, AI and pricing.
PostHog vs TrackJS: Results at a glance
My own Express and Vite setup produced these verdicts. Public source maps, a framework that PostHog's wizard supports, or alerts wired to a channel could move a few.
Area
Better in my test
Why
Setup
PostHog
More switches, all documented; TrackJS's own Express handler hung 5xx responses
Browser errors
Tie
Each one received all the storefront crashes once configured
Server errors
PostHog
Source lines read from disk and a trace per error; TrackJS shows a file and line only
Source maps
PostHog
Private upload at build time; TrackJS needs public files or a drop per error
Debugging an error
PostHog
Code, recording, timeline and trace on one issue
Browser to server
TrackJS
Each fetch in its timeline opens the matching server exception
Error grouping
PostHog, narrowly
Both split the payment bug; TrackJS also split by IDs and quantities
Session replay
PostHog
Replay is built in; TrackJS has none
Releases and regressions
PostHog
Reopened the returning bug; TrackJS left it marked Fixed
Performance
PostHog
Found the slow query by version; TrackJS has no performance data
Logs
PostHog
A logs product linked to traces; TrackJS keeps console lines as telemetry
Alerts
Not compared
No delivery channel was set up in either
AI-assisted debugging
TrackJS
Read the bad release more carefully, with no code available to either
Price
PostHog
A free tier with 100,000 exceptions a month; TrackJS has no free plan
How I tested PostHog and TrackJS
The test app is a small online bookstore built to fail. It has an Express API backed by SQLite, a Vite storefront with hash routes, a fake price service and a background job that builds a sales report. Both tools received the same planted failures from the same code, driven by scripted shoppers in a headless browser.
The planted problems were:
Browser crashes: a wishlist button that reads from a missing object, and failed API calls the storefront reports itself.
Server crashes: a checkout that throws on an unknown coupon, a book page that reads a missing record, and an out-of-stock error.
A flaky dependency: the price service returns 503 now and then.
Async failures: an unhandled rejection from a recommendations call, and a report job that throws.
A slow query and a new bug: turned on only in the third release.
The releases
Release
What I tested
1.0.0
Installing both, first errors, source maps, error pages
1.1.0
Regression detection: a resolved bug shipped again with no fix
1.2.0
The bad deploy: checkout's database lookup slows down and payments start failing
The 1.2.0 release mattered most. A real bad deploy rarely fails loudly, and this one mixed a slowdown with a new error on the same code path, which is the kind of release you most need a tool to explain.
SDKs and test limitations
Platform
PostHog
TrackJS
Server
posthog-node 5.57.2, plus OpenTelemetry for traces, logs and metrics
trackjs-node 1.3.0
Browser
posthog-js 1.441.0
trackjs 3.10.4
Plan
Free, US Cloud
Trial priced by page views
Scope: TrackJS sells browser error monitoring with a Node add-on. It doesn't claim tracing, logs, replay or performance, so I judged it on errors first and treat those gaps as outside its scope.
Counts: each tool saw its own traffic runs, so error and event counts aren't comparable one to one.
Local source maps: the storefront ran on localhost, which rules out TrackJS's automatic source maps.
Headless shoppers: PostHog's browser SDK ignores headless browsers by default, so I turned that filter off for the test.
No repository connected: neither AI assistant could read the code.
Alerts: I didn't connect Slack, email or any other channel to either tool.
Setup and onboarding
Setup shows how much of a tool you have to configure before it tells you anything useful. PostHog asks you to choose products and settings. TrackJS asks for a token and one handler.
PostHog: More products, more switches
You start PostHog by naming a goal. Mine was "Find and fix issues", and PostHog ticked a few products in response:
Error Tracking isn't among them. I added it, with Logs and Metrics, from "Show all products".
The install page leads with an AI wizard that has no Express option, so I used the manual Node.js page:
The note about setupExpressErrorHandler matters, because Express catches errors before the SDK can see them. The install I had was too old for that helper, and npm install posthog-node@latest fixed it.
Three more switches decided what I saw:
Headless browsers are dropped by posthog-js unless you set opt_out_useragent_filter: true, which only matters for test traffic like mine.
Replay stayed switched off in project settings, though onboarding had it ticked.
Exception autocapture for the web is a project setting, or the capture_exceptions: true option in code.
"Installation complete" appeared as soon as the server sent its first event. The Logs step got stuck behind a loading overlay until I closed it.
TrackJS: A token, and one handler to work around
TrackJS starts with a script tag and its token, then a four-step wizard: Agent, Applications, Team and Ignore.
The browser side worked on the first try. The application form was less forgiving:
The key fills itself from the name as you type, so my own typing doubled it. Keys can't be edited afterwards, only renamed, so the fix was a new application.
The server side had a real bug. In trackjs-node 1.3.0, TrackJS.Handlers.expressErrorHandler() ignores the options you pass it, reports the error and never calls next(). Following the documented Express setup, every request that hit a 5xx error hung with no response. I reproduced it on a minimal Express 5 server, then worked around it in the test adapter by passing the error on myself.
Setup comparison
Capability
PostHog
TrackJS
Install path
AI wizard or manual SDK pages
Script tag, npm module or legacy snippet
Express support
✔: setupExpressErrorHandler, current package required
✘: documented handler hangs 5xx requests in 1.3.0
Defaults to change
Error Tracking, replay, headless filter, web autocapture
None for the browser
Server and browser
One project
One application, two agents
Rough edges
Logs step stuck behind an overlay
Keys can't be edited; /settings opens an error page
Verdict: PostHog. It took more switches to get going, but each one was documented. TrackJS's server handler broke the app's error responses until I patched around it, and anyone who follows its docs on Express hits that.
Error capture
Capture is the minimum: every planted failure should arrive, once, with enough context to tell where it came from.
PostHog: Every browser error once the filter was off
With the headless filter switched off, PostHog's issues list held every browser failure: the wishlist crash, the storefront's own API errors and the failed tracking request.
Each row has occurrences, sessions and users, with status, severity and assignee you can set inline.
On the server, it caught the coupon, book, out-of-stock, price service and report job errors. Two details stood out:
The unhandled promise rejection never arrived. My reading is that posthog-node waits for Node to rethrow such rejections, and the app's own rejection handler stops that from happening.
Anonymous requests count as new users. Each request without a signed-in user got a fresh ID, so the price service error showed 24 users for 24 events.
TrackJS: Every failure, and some of them twice
TrackJS received every planted failure, including the unhandled rejection and the report job. After a clean run, it showed 99 errors in 29 groups from 4 users.
It also adds automatic network errors next to the app's own reports:
The checkout failure appears once as the storefront's own error and once as TrackJS's 500 : POST /checkout. Expect double rows for every failed API call unless you turn the network capture off.
TrackJS also turns console.error into error reports by default. A "Cannot set headers after they are sent" line became its own group, which other tools I've tested only logged.
Capture comparison
Capability
PostHog
TrackJS
Browser crashes
✔: after turning off the headless filter
✔: by default
Server crashes
✔: all request errors
✔: all request errors
Unhandled rejection
✘: missed in my setup
✔: captured
Background job
✔: captured
✔: captured
Automatic network errors
✘: the app's own reports only
✔: added beside the app's reports
Console errors as reports
✘: not by default
✔: on by default
User counts
Anonymous requests inflate users
Per signed-in user
Verdict: Tie. TrackJS caught more by default, including the rejection PostHog missed. PostHog's rows carried more per issue, and it reported each failure once.
Debugging an error
Once an error lands, the question is how quickly the page tells you which line failed and what the user was doing.
PostHog: Code, recording and trace on one issue
On the server, posthog-node reads source files from disk, so the coupon error showed the failing line with its neighbours:
Line 150 is highlighted, and "Show 1 vendor frame" hides the Node internals. No repository link was needed.
Browser errors get a Timeline tab with the session's pageviews, exceptions, custom events and logs:
Once replay was on, the Recording tab played the moment of the crash:
The cursor is on "Add to wishlist", and the page shows who was signed in. At the Normal privacy setting only inputs are masked, so page text stays readable.
The Properties tab had the URL, library version and my custom fields, but no request body.
TrackJS: A transcript of the visit
A TrackJS error opens on its telemetry timeline:
Clicks come with the element's HTML, fetches with method, status and duration, and hash navigations in order. With "Errors on Page" you can jump between the errors one page load produced, and General Information adds Time On Page and the viewport.
Server errors are thinner. The coupon error showed server.js 150:45 with no code lines, no request body and no headers. Its timeline also mixed this request's breadcrumbs with console lines from minutes earlier, such as the app's startup messages. The Node agent added the machine's hostname, username and working directory to every server error by default.
Debugging comparison
Capability
PostHog
TrackJS
Server code lines
✔: read from disk
✘: file and line only
Browser code lines
✔: after a source map upload
✔: after a manual map drop
Activity before the error
Timeline of events and logs
Telemetry of clicks, fetches and console
Session recording
✔: on the issue
✘: not offered
Request body
✘: not captured
✘: not captured
Per-request isolation
✔: events tied to the session
Partly: console history leaks in
Verdict: PostHog. Its issues had the code, the recording and the trace. TrackJS's timeline is the clearest single view of what a browser did, but its server errors stop at a line number.
Source maps
A minified stack is useless in production, so how a tool gets your source maps decides whether browser errors are readable at all.
PostHog: Private upload, and a new issue for each mapped error
PostHog's onboarding offers three options: unminified code, public maps it fetches, or private upload at build time. I used posthog-cli sourcemap inject and upload, and the wishlist frame resolved:
The frame now reads ../../src/pages.js@121:13, with line 122 highlighted.
The upload had a side effect:
PostHog builds the fingerprint from the resolved frames, so the minified and mapped versions of the same crash became two issues. You'd see this once per bug when you first add maps.
TrackJS: Public maps, or a drop that doesn't stick
TrackJS fetches source maps from your script's public URL. On localhost, the stack said so:
Dropping the map file on the stack did the job:
Sourcemap Support switched to ON, and the frame read ../../src/pages.js 122:13. TrackJS applies the map in your browser only, so after a reload the same error was minified again. For maps to stick, the files must sit on a public URL, which you can limit to TrackJS's IP addresses or a secret header.
Source map comparison
Capability
PostHog
TrackJS
Private upload
✔: CLI at build time
✘: not offered
Public fetch
✔: offered
✔: the automatic mode
Manual map
✘: not needed
✔: per error, not saved
Side effects
Mapped errors open new issues
None
Verdict: PostHog. Its private upload fits a normal build pipeline. TrackJS works well once maps are public, but private builds get only a manual drop that you repeat on every error.
From the browser to the server
When a browser request fails, you want to reach what the server did with it. Neither tool sells distributed tracing for the browser, and each found its own way across.
PostHog: A server trace from the error, a session from the browser
Each PostHog server error has "View trace", which opened the coupon request's trace:
It shows the request at 2.67 ms, eight spans, the Express middleware and my custom SELECT book for checkout span. What it lacks is the browser half: the storefront SDK records no spans, so the trace opens at the API. The two sides connect through the session ID.
TrackJS: A link on every fetch
The Node agent stamps responses with a correlation header that the browser agent stores, which puts a link beside each fetch:
On the failed checkout, that link led to the server's coupon exception for the same request. It appears on successful fetches too, and on a 404 with nothing behind it, it led to a page saying the error doesn't exist.
Browser-to-server comparison
Capability
PostHog
TrackJS
From a server error
✔: View trace
✘: no trace
From a browser request
Through the session ID
✔: link to the server error
Browser spans
✘: not created
✘: not created
Server timing
✔: spans with durations
✘: not recorded
Verdict: TrackJS. From the browser side, it went straight from a failed fetch to the exception it caused. PostHog's trace is better evidence once you're on the server, but it doesn't start at the click.
PostHog's trace began at the server, and TrackJS's link landed on an error without the work that led to it. I also tested the same storefront visit in Better Stack, which drew the browser and the API on one timeline:
Each click and fetch sits above the server spans it triggered, so a slow or failing step is visible without switching tools.
Grouping decides whether one bug is one row. Too loose and a new bug hides in an old one. Too strict and one bug fills the list.
PostHog: Grouped by stack, split by Node's internals
PostHog ignores the message and groups by stack frames, so different charge amounts didn't split the payment error. On 1.2.0, it still became two issues:
Both issues have the same two lines from my code. One also includes Node's internal timer frames, hidden behind "Show 2 vendor frames" yet still part of the fingerprint. The slow query changed the async path, so the same throw produced two different stacks.
That release split older bugs too. The coupon error gained two sibling issues, and the out-of-stock error gained two, while errors whose async path didn't change kept their single issue.
The fix is in Configuration:
Grouping rules match on exception properties, first match wins. You can also merge issues by hand from the Fingerprints panel. I didn't create a rule.
TrackJS: Grouped by message, split by every value in it
TrackJS groups by message text, so the payment amount decided the group:
Three failed charges became three server groups with one event each, plus a browser copy. The same rule split earlier errors by book title, quantity and ID:
Automatic URL grouping rewrites the URLs TrackJS records itself, such as 500 : GET /books/${books}, but not URLs inside the app's own messages. Each tracking request with a different ID list became its own group, six in all. "Create Group" and Settings, Error Groupings can correct this. I didn't test them.
Grouping comparison
Capability
PostHog
TrackJS
Grouping key
Stack frames
Message text
Payment bug on 1.2.0
2 issues
3 server groups and 1 browser group
Values in messages
✔: ignored
✘: each value splits
Timing changes in Node
✘: new issues
✔: no effect
Correction tools
Grouping rules, merge by hand
Create Group, Error Groupings, not tested
Verdict: PostHog, narrowly. Both broke one bug into several rows on the release that mattered. PostHog's split came from a timing change and needed a rule. TrackJS splits on every value a message carries, so the list grows with your data.
PostHog split the payment bug on its stack, and TrackJS split it on every amount. In my Better Stack test, the same release produced one payment group:
All the amounts sit in that group, with the throwing lines under the stack, and the coupon bug kept one group across three releases. After the deploy, the list grew by a single row.
Replay lets you watch what a user did, so you skip piecing it together from events. It's the clearest product difference between these two.
PostHog: Replay in the same project, off until you turn it on
Session replay is part of PostHog, but it was off at the project level until I enabled it:
Until then, every error said "Replay was not active". Console logs and network timings were already on, and I added header and body capture, Web Vitals autocapture and dead-click autocapture.
After that, the replay home listed recent sessions:
It showed "15 recently active recordings", with a "Session highlights" scanner that uses AI credits and "Summarize this recording" under the player. I didn't test either, or the Web Vitals reports.
TrackJS: A timeline with no recording
TrackJS has no replay. Its timeline records clicks, inputs with masked values, navigations, fetches and console lines, which covers much of what you'd watch a recording for. It doesn't show you the page.
Replay comparison
Capability
PostHog
TrackJS
Session replay
✔: off by default at the project level
✘: not offered
Replay on the error
✔: Recording tab
✘: not offered
Text masking by default
Inputs only
Input values masked in telemetry
Web Vitals
Included, not tested
✘: not offered
Verdict: PostHog. It records the session and links it from the error. TrackJS's timeline is a good substitute for many bugs, but it isn't a recording.
Release tracking and regressions
The release test was simple. I resolved the coupon bug on 1.0.0 and left its code untouched for 1.1.0.
PostHog: Reopened, with no regressed label
PostHog's status menu has Active, Resolved and Suppressed, with no option to resolve in a future version. Resolving showed a toast I hadn't seen in an error tracker before:
"Tell them it's fixed" would email the two signed-in users who hit the bug. I didn't send it.
On 1.1.0, PostHog reopened the issue by itself:
It went back to Active, from 44 to 64 occurrences. There's no "regressed" label, so in the list it looks like any other open issue.
The Breakdown panel answered which release brought it back:
Its bars put 44 of the occurrences on 1.0.0 and the newer 20 on 1.1.0, and the same panel splits by any custom property.
Releases themselves were harder. They come from source map uploads, and by default PostHog names them after the git commit:
The release is chosen at the inject step, so passing --release-version only to upload changed nothing. With the flags on inject as well, 1.2.0 got its own release. The issue's Releases panel also stayed empty until events carried $app_version with the dollar sign.
TrackJS: Fixed is a label
TrackJS lets you set a status from a short menu:
Fixed, Investigating and the rest are labels with no version attached. Here's the coupon row once 1.1.0 traffic had run:
It grew from 7 to 12 events and still said Fixed. The only sign it came back was inside the group:
With Show Versions on, 1.1.0 appears in red and "Versions Impacted" reads 2. The Versions page compares error counts only, and on 1.2.0 it made the bad release look like the healthiest:
1.2.0 had 68 errors against 102 on 1.0.0, because slow checkouts let less traffic through. That's a limit of counting errors alone, and a reason not to judge a release on this page.
Release comparison
Capability
PostHog
TrackJS
Fixed bug returns
✔: reopened automatically
✘: stays Fixed
Regression label
✘: shown as Active
✘: none
Resolve in a future version
✘: not offered
✘: not offered
Errors by version
✔: Breakdown on any property
✔: Show Versions chart
Release records
✔: from source map uploads, git commit by default
✘: versions only
Notify affected users
✔: "Tell them it's fixed"
✘: not offered
Verdict: PostHog. It caught the returning bug, which TrackJS didn't. You'd still want a regressed label, and you'll need to pass the release flags at the right step.
PostHog reopened the coupon bug as an ordinary Active issue, and TrackJS kept it marked Fixed. I shipped the same unfixed release to Better Stack, which labelled the comeback:
Only that row turned to a red "Reoccurred", so the bug that came back stands apart from the ones that never left.
On 1.2.0, the checkout's book lookup turned slow. An error tracker without performance data can't see that unless something fails.
PostHog: The slow query by version, in two clicks
PostHog's Operations view lists every span name with p50, p95 and error rate. Filtered to the previous release, checkout looked healthy:
There, checkout's p95 sat at 4.21 ms, and the version facet offers each of the three releases. Across all versions, the same table changed:
POST /checkout reached a p95 of 4.76 s, and further down, SELECT book for checkout had a p95 of 2.93 s against a p50 of 0.15 ms. Sorting by p95 and filtering by version found it.
One false lead came first: GET /search at 1.23 s. Its database span was tiny, and the delay lived in untraced code ahead of it on every release.
TrackJS: A duration in one timeline
TrackJS doesn't measure request timing. The slowdown showed up only because one slow checkout also failed:
That checkout request ran for 4,073 ms, where 1.0.0 checkouts had finished in roughly 15 ms. The server error for the same request had the app's own slow query warning in its telemetry, because the agent keeps console.warn lines. Slow checkouts that succeeded left nothing at all.
Performance comparison
Capability
PostHog
TrackJS
Request latency
✔: p50, p95 and p99 per operation
✘: not measured
Slow query
✔: own span with percentiles
Only as an app log line in a failed request
Latency by release
✔: version facet
✘: not offered
Successful slow requests
✔: recorded
✘: invisible
Verdict: PostHog. It found the slow query and the release that caused it. TrackJS isn't built for this, and it saw the slowdown only by accident.
PostHog found the slow query through its percentiles, which is a fair result, and TrackJS saw it only in one failed request. In Better Stack, I opened a single 1.2.0 checkout and got both problems in one request:
The lookup took 1.53 s of a 2.19 s request, and the rejected charge 660 ms. The logs for that request were a filter away:
The slow-query warning TrackJS caught by luck shows here for any request you filter to.
Logs explain what an error page can't, such as what the app was doing before the throw.
PostHog: A logs product linked to traces
PostHog took the app's logs over OpenTelemetry into its own viewer:
It held 1,068 logs in the hour, 968 Info and 100 Error, with Patterns, Group and Live tail views and a SQL tab. From a trace, the span panel's Logs tab lists the logs for that request:
That's three logs for the whole checkout trace, one click from the error.
TrackJS: Console lines as telemetry
TrackJS has no logs product. Console output appears in each error's timeline as telemetry, which is how the slow-query warning surfaced. On the server, that buffer also held older lines from other requests, so it isn't a reliable per-request log.
Logs comparison
Capability
PostHog
TrackJS
Log storage and search
✔: own viewer with SQL
✘: not offered
Logs per request
✔: from the trace
Partly: console lines on errors
Live tail
✔: included, not tested
✘: not offered
Verdict: PostHog. It stores and links logs. TrackJS keeps console lines only when an error happens.
Alerts
Neither tool sent me an alert, because I didn't connect a channel to either. Here's what each offers.
PostHog's issues list warns you about it directly:
It can alert on new, reopened and spiking issues once you pick a destination such as Slack, Teams or PagerDuty. Spike detection and severity rules sit in Configuration.
TrackJS configures notifications per application:
Summary emails go out daily and weekly unless you turn them off. New Errors, Trending Errors and Error Rate Increases go to email, Slack or Teams. New Errors keys on message text, so a returning Fixed error never triggers it, and each new payment amount would.
Capability
PostHog
TrackJS
New errors
✔: new issues
✔: new messages
Returning bugs
✔: reopened issues
✘: not offered
Spikes or trends
✔: spiking issues
✔: trending and rate increases
Channels
Slack, Teams, PagerDuty, others
Email, Slack, Teams
Uptime and status pages
✘: not offered
✘: not offered
Verdict: Not compared. Neither tool delivered an alert in my test. On paper, only PostHog alerts on a bug that comes back.
AI-assisted debugging
Both tools offer an assistant on the error, and I tested both under the same condition: no repository connected, so neither could read the code beyond the stack.
PostHog: Fluent, and willing to invent
From any PostHog issue, "Open Fix prompt" hands a fix or explain prompt to PostHog AI or to an external coding agent. For the coupon error, PostHog AI got the mechanism right: the code checks that a coupon was sent and never checks that it exists. Then it filled the gap with guesses:
The coupon codes it lists aren't the app's real ones. On the payment error, it went further:
It said the amount in the message caused the two issues, although each issue held several amounts. It took "upstream timeout" at face value, sent me to the gateway's status page, and wrote a "plausible reconstruction" of code it never saw. It didn't connect the error to 1.2.0 or the slow query.
TrackJS: Careful, and clear about its limits
TrackJS's AI Debugger runs when you open the tab and sends sanitized error data to OpenAI. On the payment error, it placed the failure and the release:
It put the throw at server.js:173 on 1.2.0, ruled out a declined card, and used the timeline to note the retry attempt. Its fixes treated the two problems separately:
One item flags the slow book lookup as its own latency issue, a step PostHog AI never took. Like PostHog, it trusted the error message and didn't find the every-fifth-charge counter. On the wishlist error, it said outright that the report didn't include enough source code to choose between two causes.
AI comparison
Capability
PostHog AI
TrackJS AI Debugger
Where it runs
PostHog AI, or sent to coding agents
On every error, by default
Code access in my test
✘: stack frames only
✘: event data only
Payment error cause
✘: blamed the message and the gateway
Partly: location and release right
Slow query
✘: not mentioned
✔: named as a separate issue
Invented details
✘: guessed coupons and code
✔: said when evidence was missing
Verdict: TrackJS. With the same lack of code, it stayed within its evidence and kept the slowdown apart from the payment error. PostHog AI's hand-off to coding agents may do better with a repository, which I didn't test.
Neither assistant here found the every-fifth-charge failure, and PostHog AI invented the code it couldn't see. I asked Better Stack's AI SRE what broke in 1.2.0, also with no repository:
It noticed that only checkout's queries had slowed to seconds, and then it counted the charges:
Ten of 48 charges failed, every one on 1.2.0, so both problems came with a size. That answer took about four minutes and $0.49.
PostHog bills each product by usage above a monthly free tier, with no base fee. TrackJS bills by page view, and errors don't count toward the bill.
These prices come from each vendor's pricing page. I read PostHog's on October 28 and TrackJS's on November 4, 2026, and rechecked PostHog's free tier on November 4. Prices change, so check them again yourself.
Free plans and trials
Item
PostHog Free
TrackJS
Price
Free, no card
✘: no free plan
Trial
Not applicable
Free trial, 1 million page views in mine
Errors
100,000 exceptions a month
Not billed
Session replay
5,000 recordings a month
✘: not offered
Logs
10 GB a month
✘: not offered
AI
500 PostHog AI credits a month
AI Debugger during my trial
Projects
1
Not stated for the trial
PostHog's plan step showed the same free tier on both its plans:
On Free, events past the allowance are dropped. The pay-as-you-go plan has no base fee, permits six projects and keeps recordings for 90 days, where Free keeps them for one month.
My TrackJS trial ran on these terms:
Entry-level paid plans
Item
PostHog Pay-as-you-go
TrackJS Starter
TrackJS Professional
Base price
$0
$49 monthly, $45 a month yearly
$99 monthly, $91 a month yearly
Volume included
The free tier above
100K page views
1M page views
Errors
Billed above 100,000
20 saved a minute
60 saved a minute
Retention
Recordings 90 days
10 days
15 days
Projects or applications
6
1
5
TrackJS Business costs $199 a month, or $183 yearly, for 5 million page views, 90 errors a minute and 30-day retention. TrackJS's page lists an AI Code Debugger but doesn't say which plans include it.
Usage beyond the free allowance
These are PostHog's per-unit rates from my October 28 reading. The November 4 page sent me to its calculator for them.
Item
PostHog
Exceptions
$0.000370 each from 100,001 to 325,000
Recordings
$0.0050 each in the first paid band, 5,001 to 15,000
Logs
$0.25 per GB
Spending caps
✔: per product
Comparing the actual cost
Picture a shop that gets 100,000 visits a month. On a yearly plan, TrackJS Starter costs $45 a month for that, with 10 days of history and one application. PostHog's free tier covers 100,000 exceptions, 5,000 recordings and 10 GB of logs before you pay anything, and it adds tracing, which TrackJS doesn't have.
The catch is the shape of the bill. TrackJS's price doesn't move when a release throws thousands of errors, because it only saves 20 a minute on Starter. PostHog's grows with exceptions and recordings past the free tier, so set its per-product caps before a bad deploy finds them for you.
Verdict: PostHog. For a small team it's free, and it covers more ground. TrackJS's flat page-view price is easier to predict, and cheap if browser errors are all you need.
Full feature comparison
Feature
PostHog
TrackJS
Browser errors
✔: after turning off the headless filter
✔: by default
Server errors
✔: with source lines
✔: file and line only
Automatic network errors
✘: not offered
✔: beside the app's reports
Source maps
✔: private upload
✔: public fetch or manual per error
Session replay
✔: off by default
✘: not offered
Activity timeline
✔: events and logs
✔: clicks, fetches, console
Browser to server
Session ID and server trace
✔: correlation link
Grouping
Stack frames, Node internals included
Message text
Regression detection
✔: reopens, no label
✘: stays Fixed
Release records
✔: git commit by default
✘: versions only
Tracing
✔: OpenTelemetry
✘: not offered
Logs
✔: own product
✘: console telemetry only
Metrics
Alpha, behind a preview
✘: not offered
Alerts
Included, not tested
Included, not tested
AI
PostHog AI and coding-agent prompts
AI Debugger on every error
Free plan
✔: 100,000 exceptions a month
✘: trial only
Which should you choose?
Decide how much of your stack one tool should watch.
Choose PostHog if you want errors next to everything else
PostHog gives an error its code, its recording, its trace and its logs, and it reopened the bug that came back. Its Operations view found the slow release on its own. The free tier is large enough to run a small product on.
The trade-offs are the setup and the grouping. Replay, headless capture and web exception autocapture each needed switching on, releases default to git commits, and on Node a timing change can split one bug into several issues. If you're weighing PostHog against a replay-first tool, our LogRocket vs PostHog comparison covers that side.
Choose TrackJS if your bugs live in the browser
TrackJS caught every failure by default, linked each failed fetch to its server error, and its AI Debugger was the more careful of the two. Its price is flat and low, and its timeline is the quickest read of what a page did before it broke.
It stops there. A Fixed error that returns stays Fixed, every value in a message makes a new group, and there's no performance data, so a slow release can look healthy. Its Express handler also needs the workaround described above. For a broader platform against it, see our Sentry vs TrackJS comparison.
FAQ
Does TrackJS have session replay like PostHog?
No. TrackJS keeps a telemetry timeline of clicks, inputs, navigations, fetches and console lines on each error. PostHog records the session and links it from the error.
Does PostHog group errors by message?
No. PostHog groups by stack frames, so different values in the message stay in one issue. On Node, its fingerprint also included internal async frames, which split one bug into two issues when a release changed the timing.
Can TrackJS monitor my Node.js server?
Yes, through trackjs-node, which reports server errors and links them to browser requests. In version 1.3.0, its Express error handler left 5xx requests hanging, so check your error responses after you install it.
Which is cheaper?
PostHog, if you stay within its free tier of 100,000 exceptions and 5,000 recordings a month. TrackJS has no free plan, and Starter costs $45 a month on a yearly plan for 100,000 page views.
Final thoughts
The real decision is between breadth and focus. PostHog shows you more of what happened around an error, and it asks you to configure, group and release-tag it carefully to get there. TrackJS gives you less to set up and less to see, and its AI was the more honest of the two about what it didn't know.
On the release that mattered, PostHog showed the slowdown and reopened the old bug, while TrackJS's version page suggested the deploy had gone well. If a quiet error count would reassure your team, TrackJS will reassure it at exactly the wrong moment.