PostHog vs Raygun: A Hands-On Error Tracking Comparison for 2026

Stanley Ulili
Updated on November 11, 2026

Adding Raygun's Node.js APM package to my test app quietly erased the message and stack trace from every native JavaScript error its crash reporter sent. The profiler wasn't even running. Adding PostHog's tracing to the same app did the opposite: it put a "View trace" button on every server error and found the slow database query behind a bad release in two clicks.

Both products are suites, and that's the real subject of this comparison. PostHog is a product analytics platform that has grown error tracking, session replay, logs, tracing and an AI assistant, all billed by usage above a generous free tier. Its tracing runs on OpenTelemetry, so the same SDKs you'd use anywhere feed it.

Raygun is a family of three products, each bought on its own: Crash Reporting for errors, Real User Monitoring for page speed, and APM for the server. Its crash reporter has the more mature release workflow of the two, with version-aware resolving and a page for every deployment.

I ran both against the same bookstore app on the browser and the server, through the same three releases, so every section here is a direct comparison. Where I didn't test something, like Raygun's MCP server for AI assistants, the section says so.

The sections below follow a bug's path through each product, from install and capture to grouping, release checks, speed, AI and the bill.

PostHog vs Raygun: Results at a glance

Every verdict here rests on a single Express and Vite app, with each product configured by its own docs on its free plan or trial. Another stack or a paid Raygun plan could change some of them, especially around source maps.

Area Better in my test Why
Setup PostHog, narrowly Both had snags; Raygun's one-app-per-tier model and manual map labels cost more time
Error capture PostHog Browser and server in one list; Raygun splits them into two applications
Source maps PostHog CLI upload on the free plan; Raygun's API upload needs a paid token
Debugging an error PostHog Server source lines, a linked trace and a replay tab on one page
Session replay PostHog Video replay; Raygun's RUM sessions are timelines
Error grouping Neither Both split the new payment bug and reopened old bugs as new rows
Releases and regressions Raygun Resolve in next version, a Regressions tab per deployment
Performance PostHog p95 by version exposed the slow query; Raygun's release comparison called the bad release faster
Logs and metrics PostHog Logs and metrics products; Raygun has neither
Alerts Not compared No destination was connected in either
AI-assisted debugging Not compared PostHog AI was tested; Raygun's MCP server was not
Price PostHog A free tier with 100,000 exceptions; Raygun has no free plan

How I tested PostHog and Raygun

The test app, monitoring-lab, sells books and fails in scripted ways. Its storefront is built with Vite and talks to an Express server that stores data in SQLite. A fake price service misbehaves on purpose, and a sales report is generated once a minute. Each monitoring product plugs into the same browser and server adapter slots, so the app code is identical across tests.

The planted failures:

  • Browser: the wishlist button throws a TypeError, order tracking leaves a rejected promise unhandled, and some API calls return 404, 500 or 502.
  • Server: checkout crashes on an unknown coupon, looking up a missing book crashes too, sold-out books raise a handled error, price lookups get a 503, and a recommendations promise is left to reject.
  • Background job: some sales report runs fail.

Headless Chromium drives two signed-in shoppers, alice and bob, plus anonymous visitors. A third shopper, carol, calls the API directly.

The releases

Release What I tested
1.0.0 Install, first errors from both tiers, maps and the error page
1.1.0 The coupon bug marked fixed, then shipped again unchanged
1.2.0 A bad deploy: checkout's book query slows to seconds, and every fifth payment fails

A good tool should surface both 1.2.0 problems together: the slowdown and the new exception.

SDKs and test limitations

Platform PostHog Raygun
Browser posthog-js 1.441.0 raygun4js 3.1.4, with RUM
Node.js server posthog-node 5.57.2 with the Express handler raygun 2.2.10 with the Express handler
Tracing, logs, metrics OpenTelemetry SDK to PostHog's OTLP endpoints APM agent and raygun-apm 2.3.0, 1.0.0 only
Plan Free plan, no card 14-day trial
  • Runs were separate: Raygun ran on October 23 and PostHog on October 28, with the same traffic script. Event counts don't match one to one.
  • Raygun APM covers 1.0.0 only. Installing its Node.js package broke crash reporting, so I removed it before the 1.1.0 and 1.2.0 runs. Raygun's timing for 1.2.0 comes from RUM in the browser.
  • Raygun's MCP server wasn't connected, so AI is PostHog only.
  • No alert destinations were set up in either product.

Terms in each tool

Concept PostHog Raygun
A group of the same error Issue Error group
One occurrence Exception event Instance
Fixed state Resolved Resolved, optionally in a version
Silenced state Suppressed Ignored or Permanently ignored
Release $app_version, or a source map release setVersion, plus deployments
Browser and server One project Two applications
A user's visit Session recording RUM session timeline

Setup and onboarding

Both products install from npm on each tier. The differences were in what onboarding assumed and which defaults I had to change.

PostHog: Pick a goal, then add error tracking yourself

PostHog's onboarding opens with a goal. I picked "Find and fix issues", described as watching recordings, monitoring errors and searching logs. The products it then preselected left out Error Tracking itself:

PostHog onboarding with Error Tracking not preselected

Error Tracking, Logs and Metrics had to be ticked by hand under the full product list. PostHog then suggests its AI install wizard, but that wizard supports no Express option, so the manual SDK page was my route. The Node.js page flags the one line Express apps need:

src/monitoring/adapters/posthog.js
import { PostHog, setupExpressErrorHandler } from 'posthog-node';

const client = new PostHog(process.env.POSTHOG_TOKEN, {
  host: 'https://us.i.posthog.com',
  enableExceptionAutocapture: true,
});

// ...your routes...

Express catches route errors itself, so without that handler they never reach PostHog. Three defaults cost me time:

  • Headless browsers are filtered out. Headless Chromium stayed silent until opt_out_useragent_filter: true went into the init options, while a normal Chrome window reported right away.
  • Session replay was off at the project level, although I'd selected the product. Every error said no recording existed until I switched it on.
  • An older posthog-node lacked a function my adapter used, and upgrading fixed it.

Raygun: One application, one product at a time

Raygun's onboarding creates an application per part of your system and sets up one product at a time:

Raygun onboarding creating the first application

The marked text explains that frontend, backend and mobile each get their own application, with their own API key and error list. Step three waits for a first event before you can leave, and I had to send a request with a bad coupon to get past it.

On the server, two Express hooks cover breadcrumbs and errors:

src/monitoring/adapters/raygun.js
import raygun from 'raygun';

const client = new raygun.Client().init({
  apiKey: process.env.RAYGUN_API_KEY,
  reportUncaughtExceptions: true,
});
client.setVersion('<your_release>');

app.use(client.expressHandlerBreadcrumbs.bind(client));
// ...your routes...

The browser was harder. raygun4js installed from npm reads its settings only at the page's load event, so imported from a module that loads later, it never started and sent nothing. The fix was to copy the CDN snippet's queue and import the library after load.

Raygun's browser loader, as the adapter does it ```javascript [label web/src/monitoring/raygun-browser.js] window.RaygunObject = 'rg4js'; window.rg4js = window.rg4js || function (...args) { (window.rg4js.o = window.rg4js.o || []).push(args); }; rg4js('apiKey', import.meta.env.VITE_RAYGUN_API_KEY); rg4js('enableCrashReporting', true); rg4js('enablePulse', true); [highlight]window.addEventListener('load', () => import('raygun4js'));[/highlight] ``` Calls made before the library loads sit in the queue, and the library reads them when it starts.

Worth turning on: in PostHog, enable session recording and network body capture in project settings before your first real traffic, since neither was on for me. In Raygun, create the browser and server applications with the same version string, because deployments and regressions are tracked per application.

Setup comparison

Capability PostHog Raygun
A single home for both tiers ✔: shared project ✘: an application per tier
Express integration ✔: one error handler ✔: breadcrumbs and error handlers
AI install wizard ✔: no Express option ✘: not offered
Browser SDK from npm ✔: worked once headless filtering was off Needed a queued loader
Defaults I had to change Headless filter, replay off None beyond the loader

Verdict: PostHog, narrowly. Neither install was smooth, but PostHog's problems were settings, fixed once. Raygun's two-application model shapes everything that follows. PostHog fits teams wanting one project for the whole app, and Raygun fits teams that already think of front end and back end as separate services.

Error capture

Both products saw both tiers. How they presented them is the difference.

PostHog: One list for the whole app

PostHog's issues list held browser and server errors together, each row with occurrences, sessions, users and inline pickers for status, severity and assignee:

PostHog issues list with browser and server errors

The marked severity column was set automatically for some issues, Critical included. Three things were off:

  • The recommendations rejection never arrived, because my app registers its own unhandledRejection listener, and posthog-node doesn't add one in Node's default mode.
  • The report job's location named my adapter's span wrapper as the code that failed.
  • Anonymous requests inflated the Users column, since each got a fresh ID. The 503 error showed 24 users for 24 events.

Raygun: Two applications, two lists

The API's application listed five error groups:

Raygun error groups for the API application

The recommendations rejection was missing here too. The browser's application held eight groups in a separate list:

Raygun error groups for the browser application

The marked rows are one bug, a failed book load, split into four groups by the URL in the message. The order-tracking 404 grouped fine with different IDs, so the split depends on how the message is built. Each dashboard opened on a 7-day range, which flattened the first day into one spike.

Error capture comparison

Capability PostHog Raygun
Browser exceptions ✔: automatic ✔: automatic
Express errors ✔: with the handler ✔: with the handler
Unhandled rejection with an app listener ✘: missed ✘: missed
Background job errors ✔: wrong location ✔: captured
Both tiers in one list ✔: one project ✘: separate applications
Severity on each row ✔: set automatically, editable ✘: not offered

Verdict: PostHog. It put every failure in one list with severity and assignee on the row. Raygun captured the same bugs, but you check two lists, and one browser bug arrived as four. PostHog fits teams who triage the whole app in one pass, and Raygun fits teams with separate front-end and back-end owners.

Source maps

My storefront ran on a host neither product could fetch maps from, so both needed an upload.

PostHog: Inject, upload, and watch the release

posthog-cli runs in two steps, sourcemap inject and sourcemap upload. After that, the wishlist crash pointed to src/pages.js line 122, with the surrounding code expandable on the page:

PostHog wishlist crash with source-mapped code

Two side effects caught me out. Errors from before the upload stayed in their own issue, so the wishlist bug had a minified row and a mapped row. And the release came from git: the inject step derives it from the current commit unless you pass the release flags there too.

 
posthog-cli sourcemap upload --directory web/dist

Raygun: Manual uploads on the trial

To script uploads, Raygun wants a Personal Access Token, and trial accounts can't create one. Trial users upload files by hand in the JS Source Map Center, and each one arrives unlabeled:

Raygun Source Map Center with every file unlabeled

Every file needs its full URL typed in, and because bundle names change on each build, the labeling repeats with every release. Twice, two labels traded places after saving. With the labels finally correct, the Re-process this error for Source Maps button repaired the earlier error on the spot:

Raygun wishlist crash after source maps were applied

The frame shows src/pages.js at line 122, column 13, with the lines around it. Reprocessing old errors is a feature PostHog lacked in my test.

Source map comparison

Capability PostHog Raygun
Upload from a script ✔: CLI on the free plan ✘: needs a paid token
Manual upload Not needed ✔: with a label per file
Fixes earlier errors ✘: new issue for mapped events ✔: Re-process button
Release tagging From git unless flags are set at inject From setVersion
Server source lines ✔: read from disk ✘: not shown

Verdict: PostHog. A scripted upload you can run in CI matters more than reprocessing old errors. On a paid Raygun plan the API removes the manual labeling, which would narrow the gap.

Debugging an error

The coupon crash is a good test: it starts in a shopper's browser and fails in the API.

PostHog: Code, trace and recording on one issue

The server issue shows the code that threw, read straight from the server's disk, with no repository link needed:

PostHog server error with source lines

Line 150 is highlighted, and "Show 1 vendor frame" tucks away Node's internals. View trace then opens the request that failed:

PostHog trace for the failed checkout

The trace has eight spans, my own database span among them, and a Logs tab with the lines written during that request. Two gaps: the event's properties had no request body, and the trace starts at the server, because posthog-js doesn't create browser spans. The browser side connects through the session ID.

For the wishlist crash, the Recording tab plays the visit at the moment of the error:

PostHog Recording tab at the wishlist crash

The cursor is on "Add to wishlist", and the signed-in shopper is visible. Page text wasn't masked at PostHog's default "Normal" privacy level, only inputs.

Raygun: Request data and breadcrumbs, without code

Raygun spreads each error over seven tabs, with HTTP and Breadcrumbs doing most of the work here. The server stack trace stops at file and line:

Raygun server stack trace with no source lines

server.js:150 and one framework frame, with no code shown. The breadcrumbs make up for part of it, since they're scoped to the request:

Raygun request-scoped breadcrumbs on the server

POST /checkout, "checkout started" and "book found" belong to that one request. In the browser, breadcrumbs are automatic and include clicks, hash changes and XHR calls. Customers joins each user's RUM sessions and errors, so alice's 10 sessions and 5 errors sit on one page.

Nothing links the browser's failed checkout to the server's crash. They live in different applications, and Raygun draws no trace between them.

Debugging comparison

Capability PostHog Raygun
Server source lines ✔: from disk ✘: file and line only
Trace for the failing request ✔: View trace, with logs ✘: not linked
Request body ✘: not on the server event ✔: HTTP tab
Breadcrumbs per request ✔: Timeline tab ✔: Breadcrumbs tab
Replay at the error ✔: Recording tab ✘: not offered
Browser error to server error Through the session ID ✘: separate applications

Verdict: PostHog. Code, trace, logs and recording on one issue answered the coupon crash without leaving the page. Raygun's HTTP tab holds the request body PostHog lacked, and its request-scoped breadcrumbs are good. PostHog fits teams debugging across tiers, and Raygun fits teams who start from the request data.

PostHog's trace began at the server, and Raygun kept the browser and the API in two applications. In my Better Stack test, one storefront request carried both tiers in a single trace:

Better Stack timeline with browser and server spans together

Thirty browser spans run above seven from the API. The click and the server code it reached appear in one view, with no session ID to look up.

Follow a request from click to query

Session replay

PostHog records visits as video. Raygun's RUM records them as timelines of page views.

PostHog: Recordings with network and console

Once enabled, recordings arrived with console logs and network timings on by default, and I added headers and bodies:

PostHog replay network capture settings

The marked switches control what each recording keeps. The replay home offers a Session highlights scanner that picks recordings worth watching, using AI credits, and Summarize this recording under the player. Neither got a trial run from me.

Raygun: A timeline per visit

Raygun's RUM session page lists page views, time on each page, load times and errors, with an "Experience" rating:

Raygun RUM session timeline

It shows where the user went and how fast each page was, with no clicks or rendered pages. RUM also measures load time and Core Web Vitals across every visit, which PostHog's replay alone doesn't summarize.

Worth turning on: in PostHog, raise the replay privacy level or mark sensitive elements before recording real customers, because page text is visible at the default.

Replay comparison

Capability PostHog Raygun
Video of the visit ✔: on by setting ✘: not offered
Network calls per visit ✔: with bodies when enabled ✔: XHR timings across visits
Console ✔: per recording ✘: not offered
Page load metrics across users Web Vitals autocapture, not reviewed ✔: FCP, LCP, CLS, INP
AI summaries ✔: offered, not tested ✘: not offered

Verdict: PostHog. Watching the click that caused a crash beats reading a list of pages. Raygun's RUM is the better tool for page speed across many users, which is a different job.

Error grouping

How a tool folds events into rows decides what your list says after a deploy. 1.2.0 was the real test, because the slow query changed the async path into the crash sites.

PostHog: Ignores message text, counts Node internals

PostHog didn't split errors by their message. It did split them by stack frames from Node itself. The new payment error arrived as two issues:

PostHog payment issue including vendor frames

Both issues throw from server.js line 173. One fingerprint also includes two node:internal timer frames, which the page hides behind "Show 2 vendor frames" yet still uses for grouping. The charge amounts were mixed across both issues, which rules the message out.

The same effect gave the coupon crash and the out-of-stock error two new sibling issues each in 1.2.0. Uploading source maps had already split the wishlist crash in two. PostHog's fixes are Grouping rules in configuration, empty by default, and merging through each issue's Fingerprints panel.

Raygun: Message text in the fingerprint

Raygun went the other way. Its 1.2.0 list split the payment error by the amount in the message:

Raygun 1.2.0 error list with payment errors split by amount

"Payment gateway rejected charge of 44 USD" and "of 35.5 USD" are separate groups with the same class and stack. 1.2.0 also opened fresh groups for the coupon crash and two for the out-of-stock error, as the changed stack did in PostHog. On the browser side, the book-load error was already split by URL.

Grouping comparison

Capability PostHog Raygun
Groups by message text ✘: no ✔: in my test
Hidden vendor frames in the fingerprint ✔: they count Not tested
New payment bug Two issues Two groups, split by amount
Old bugs after 1.2.0 New sibling issues New groups
Fixing it ✔: Grouping rules, merging Not tested

Verdict: Neither. Each product turned one new bug into two rows and reported old bugs as new. PostHog's rule is safer for messages with IDs or amounts in them, and it gives you grouping rules to correct the rest.

PostHog split the payment bug by Node's timer frames, and Raygun split it by the amount charged. Better Stack kept it whole when I ran 1.2.0 against it:

Better Stack single payment error group

All 10 payment exceptions sit in one group, with the throwing code on the page. Amounts and async depth didn't create extra rows, so the release's new bug read as one new bug.

Keep one bug in one row

Releases and regressions

In 1.1.0, I marked the coupon crash fixed in each product and shipped it again unchanged. Both reopened it, under different rules, and neither marked the reopened row in its list.

PostHog: Reopens on anything, and offers to email users

Issues in PostHog move between three states, Active, Resolved and Suppressed, and none of them takes a version. Resolving the coupon crash brought up an offer I haven't seen elsewhere:

PostHog toast offering to tell users the issue is fixed

Two signed-in shoppers had hit the bug, and Tell them it's fixed would email them. I didn't send it. When 1.1.0 traffic arrived, the issue went back to Active on its own, with no regression label. The Breakdown panel showed where the new events came from:

PostHog breakdown of the issue by app version

The bars split the issue's events between the two versions, 44 from 1.0.0 against 20 from 1.1.0. Any property works there, emails and URLs included.

PostHog's release list was the weak point. Releases are created by source map uploads and named after the git commit unless you pass flags at inject, so 1.0.0 and 1.1.0 both landed on one commit release. The issue's own Releases panel stayed empty until my adapters sent $app_version with a dollar sign.

Raygun: Resolved in the next version, regression on the deployment

Raygun's resolve menu has Resolve, Resolve in version, Resolve in next version, Ignore and Permanently ignore:

Raygun Resolve in next version dialog

The dialog promises the error stays resolved for 1.0.0 and earlier, and reactivates if it shows up in a newer version. The marked checkbox, on by default, discards further events until that newer version arrives, which keeps a known bug from burning your quota.

Deployments are created by hand on the trial. My first attempt with every field filled returned a 500 page, and the second, with only the version, worked. Once 1.1.0 traffic ran, the deployment listed the bug:

Raygun 1.1.0 deployment with one regression

Regressions 1 holds the coupon crash, resolved in 1.0.0 and active again. Its activity feed reads "Error reoccurred" with the time. The errors list showed the row as plain Active, with a strip of deployment markers above the chart.

Release comparison

Capability PostHog Raygun
Fix tied to a version ✘: not offered ✔: a named version or the next one
Reopens a returning bug ✔: on any new event ✔: in a newer version
Regression label in the list ✘: none ✘: none
Release or deployment page Release list from source maps ✔: New errors, Regressions, Still occurring
Events by version ✔: Breakdown panel ✔: version split on the error
Notify affected users ✔: Tell them it's fixed ✘: not offered
Release names Git commit unless set at inject setVersion

Verdict: Raygun. Version-aware resolving and a Regressions tab per deployment are exactly what a release review needs. PostHog reopened the bug just as reliably, and its Breakdown panel and user email are good ideas, but its releases took setup to mean anything. Raygun fits teams who review each deploy, and PostHog fits teams who track bugs by user impact.

PostHog and Raygun both put the returning coupon bug back to Active, and both lists showed it as an ordinary row. Better Stack's list labeled it when I shipped 1.1.0:

Better Stack errors list with the coupon bug marked Reoccurred

The red "Reoccurred" tag is on that one row and nowhere else. You see the regression in the list itself, without opening a deployment page or a breakdown.

Spot regressions in the error list

Performance monitoring

1.2.0 made checkout's book query slow. Here the suites part ways sharply.

PostHog: p95 by version, in two clicks

Tracing → Operations lists every span name with percentiles and error rates. Filtered to 1.2.0, the slow span was obvious:

PostHog operations for release 1.2.0

POST /checkout had a p95 of 4.76 s and SELECT book for checkout had 2.93 s. Switching the version filter to 1.1.0 dropped checkout's p95 to 4.21 ms:

PostHog operations for release 1.1.0

The version facet comes from the OpenTelemetry resource, so any OTel service gets it. One trap: GET /search at 1.23 s looked suspicious first, but that gap is in uninstrumented code and is slow on every version.

Raygun: A misleading comparison, and an agent that broke errors

Crash Reporting has no timing. RUM has a release comparison, which I ran for 1.1.0 against 1.2.0:

Raygun RUM comparison calling 1.2.0 faster

It reports 1.2.0 as 34.8% faster in median load time. That compares full page loads, which didn't change, and leaves out the /checkout call, which got slow. The XHR table showed checkout's average climbing to 439 ms across all versions, but its version filter didn't apply.

On 1.0.0, I tried Raygun APM, which runs as an agent process beside your app and loads through raygun-apm. On a Mac, the profiler couldn't reach the agent without RAYGUN_AGENT_HOST pointing at localhost. Its traces showed idle time and Node internals with no app functions, SQLite queries aren't supported, and the default samples one trace per URL per minute:

Raygun APM slowest tables with methods and queries empty

The only external call recorded was Raygun's own error upload. Worse, installing raygun-apm changed global.Error, and from then on crash reporting sent native errors as "Unknown error" with no message or stack, even with the profiler off:

Raygun errors arriving as Unknown error after APM was installed

The coupon and book crashes merged into this one group, 152 events by the end of the run. Removing raygun-apm restored real messages, and an environment flag, RAYGUN_APM_CRASH_REPORTING_INTEGRATION=false, does the same with the package kept.

Why the APM package broke Raygun's own error reports When `raygun` finds `raygun-apm` installed, it loads a bridge module that swaps `global.Error` for its own constructor so errors can carry trace data. Errors V8 throws itself, like `TypeError: Cannot read properties of undefined`, then fail `instanceof Error`. The crash reporter treats them as plain objects and sends an empty message. Classes your app defines with `extends Error` still pass, which is why handled errors kept their text.

Performance comparison

Capability PostHog Raygun
Server spans ✔: OpenTelemetry ✔: separate agent and package
App code in traces ✔: my spans and Express ✘: Node internals only
Database queries ✔: custom span ✘: SQLite unsupported
Latency by release ✔: version facet RUM page loads only
Browser performance Web Vitals autocapture, not reviewed ✔: RUM with Core Web Vitals
Side effects None found Broke crash reporting

Verdict: PostHog. It found the regression in two clicks. Raygun's release comparison crowned the bad release as faster, and its APM agent damaged its own error tracker. Choose Raygun RUM for page-load metrics, and look elsewhere for server tracing.

PostHog's percentiles pointed at the slow span, and Raygun's agent added risk without seeing the query. Better Stack broke the 1.2.0 checkout into its parts:

Better Stack spans for the slow checkout

Of 2.19 s in total, the book lookup span took 1.53 s and the failing charge 660 ms. Both 1.2.0 problems sit in one request, and nothing about collecting them touched the error reports.

Collect traces without a second agent

Logs and metrics

PostHog has a logs product and an early metrics viewer. Raygun has neither, so this is mostly about PostHog.

PostHog: Logs, live tail and an alpha metrics viewer

The logs page held 1,068 lines in its first hour, with level, service and host facets and views for Patterns, Group and Live tail:

PostHog logs viewer

The same logs appear on each trace, so an error leads straight to its request's lines. Metrics needed a feature preview, its overview tab failed to load, and the viewer worked with Builder, PromQL and SQL modes. A survey asking me to rate each product popped up on first visit.

Raygun: Breadcrumbs and custom data

Raygun keeps breadcrumbs and custom data on each error and has no log search. Its notification defaults include a daily error summary and a weekly RUM update.

Logs and metrics comparison

Capability PostHog Raygun
Log storage and search ✔: 10 GB a month free ✘: not offered
A request's own log lines ✔: on the trace ✘: not offered
Custom metrics ✔: alpha ✘: not offered
Breadcrumbs ✔: Timeline ✔: per error

Verdict: PostHog. It stores and searches logs and ties them to traces. Raygun leaves logs to another product.

Alerts

I reviewed alerting in both without connecting a destination, so nothing was delivered.

PostHog: A banner until you add a destination

PostHog's issues list carries a banner until you connect somewhere to send alerts:

PostHog banner about missing alerts

It names new, reopened and spiking issues as triggers, sent to Slack, Teams, PagerDuty or other destinations. Configuration adds spike detection, rate limits, assignment, severity and suppression rules.

Raygun: Email defaults per application

Each new Raygun application starts with notifications on:

Raygun create application form with notification defaults

New error and daily summary emails are on, as is the weekly RUM update, and APM alerts are off. Because applications are separate, you set this up per tier.

Alerts comparison

Capability PostHog Raygun
On by default ✘: needs a destination ✔: new error email
Reopened errors ✔: trigger listed Not tested
Spike detection ✔: in configuration Not tested
Assignment and severity rules ✔: offered Not tested

Verdict: Not compared. Neither sent me anything. On paper, Raygun works out of the box by email, and PostHog has more rules once you connect it.

AI-assisted debugging

PostHog has an assistant inside the product, PostHog AI, plus prompts you can open in outside tools. Raygun's AI route is a remote MCP server for assistants like Claude Code or Cursor, which I didn't connect. This section covers PostHog alone.

PostHog: Fluent, and willing to guess

Every issue has Open Fix prompt, which hands a ready-made prompt to PostHog AI or to an editor-based assistant such as Cursor. On the coupon crash, PostHog AI explained the mechanism correctly, that the code checks the coupon is present without checking it exists:

PostHog AI explaining the coupon crash

It then sketched what my coupon list "likely looks like" with codes my app doesn't have. On the payment error it did worse, blaming the split on the amounts in the message, inventing code between two stack lines, and suggesting I check the gateway's status page. It never tied the failures to 1.2.0 or the slow query.

Raygun: Bring your own assistant

Raygun has no assistant inside the app. The MCP server gives an external assistant access to its error, deployment, session and APM data, and I left it unconnected.

AI comparison

Capability PostHog Raygun
Assistant in the product ✔: PostHog AI ✘: not offered
Prompts for outside tools ✔: Claude Code, Cursor, Codex MCP server, not tested
Root cause on my bugs Right on the coupon, wrong on payments Not tested
Free usage 500 credits a month Not applicable

Verdict: Not compared. PostHog AI was quick and confident, and wrong where it lacked the code. Raygun depends on the assistant you connect.

PostHog AI guessed at the payment failures, and Raygun leaves the reasoning to your own assistant. Better Stack's AI SRE took the same 1.2.0 question in my test:

Better Stack AI SRE on release 1.2.0

It traced the slowdown to the checkout query and showed 10 of 48 charges failing, all on 1.2.0. Its run cost $0.49 across roughly four minutes, working from traces and logs with no code guessed at.

Investigate a release with AI SRE

Pricing

Every PostHog product has its own monthly allowance and a usage rate beyond it. Raygun's three products each come as a fixed volume tier.

I read both pricing pages on November 11, 2026. PostHog's page sent per-unit rates to its calculator, so those rates are from my October 28 reading. Check both before you buy.

Free plans and trials

Item PostHog Raygun
Free plan ✔: no card ✘: none
Trial Not needed 14 days on every plan
Errors 100,000 exceptions a month Trial only
Session recordings 5,000 monthly ✘: not offered
Log ingestion 10 GB monthly ✘: not offered
Assistant credits 500 monthly ✘: no assistant
Projects 1 on Free, 6 on Pay-as-you-go Unlimited applications on paid plans

PostHog's plan step shows the free tier is the same on both of its plans:

PostHog plan choice with the shared free tier

On Free, events stop at the allowance. Pay-as-you-go keeps going and bills the extra, with per-product spending caps.

Entry-level paid plans

Plan detail PostHog Pay-as-you-go Raygun errors, Basic tier Raygun RUM, Basic Raygun APM, Basic
Billed yearly, per month $0 base $40 $80 $80
Billed monthly $0 base $60 $120 $120
Volume Free tier, then per unit 100,000 errors 100,000 sessions 100,000 traces
Extra volume $0.000370 per exception from 100,001 $0.001 per error $0.002 per session $0.002 per trace
Retention 2 years of events, 90 days of recordings 180 days of errors Not listed Not listed

What costs extra

Need PostHog Raygun
Server errors Included in exceptions Included in Crash Reporting
Page load metrics Web Vitals in analytics events RUM subscription
Server tracing Usage based, OpenTelemetry APM subscription and agent
Session replay 5,000 free, then per recording ✘: not offered
API uploads Included Paid plans only
Longer log retention $0.05 per GB per month ✘: no logs

Comparing the actual cost

A small app can run on PostHog for free, since its monthly allowance spans exceptions, recordings, logs and tracing. Raygun's cheapest error tracking is $40 a month on an annual plan, and adding RUM and APM to match PostHog's coverage brings it to $200 a month.

Raygun's bill is easier to predict, since each product is a fixed tier plus a clear overage rate, and Discard future occurrences keeps a known bug from eating your errors. PostHog's bill moves with every product you use, so set caps per product. For PostHog against a page-view model, see our PostHog vs TrackJS comparison.

Verdict: PostHog. It covers more for less, and free for a small team. Raygun's predictability is worth paying for only if you want its release workflow.

Full feature comparison

Feature PostHog Raygun
Browser errors ✔: posthog-js ✔: raygun4js
Server errors ✔: Express handler ✔: Express handler
Both tiers in one list ✔: one project ✘: two applications
Severity and assignee on rows ✔: inline ✘: not offered
Source map upload by script ✔: CLI, free Paid plans only
Reprocess old errors after maps ✘: new issue instead ✔: Re-process button
Server source lines ✔: from disk ✘: not shown
Request body ✘: not captured ✔: HTTP tab
Session replay ✔: video ✘: RUM timeline
Groups by message text ✘: no ✔: splits by amount or URL
Grouping rules ✔: in configuration Not tested
Resolve in next version ✘: not offered ✔: with discard option
Deployment pages ✘: release list only ✔: Regressions tab
Email affected users ✔: Tell them it's fixed ✘: not offered
Server tracing ✔: OpenTelemetry ✔: agent, broke crash reporting
Latency by version ✔: Operations facet RUM page loads only
Core Web Vitals Autocapture, not reviewed ✔: RUM
Logs ✔: with live tail ✘: not offered
Metrics ✔: alpha ✘: not offered
AI ✔: PostHog AI MCP server for your assistant
Free plan ✔: generous ✘: trial only

Which should you choose?

Both are suites. The question is which suite's center matches how your team works.

Choose PostHog if you want one project for everything

  • You debug across tiers. Server code, the request's trace, its logs and the user's recording sit on one issue.
  • Performance matters per release. Operations with a version filter found my slow query in two clicks.
  • Budget is tight. The free tier covers errors, replay, logs and tracing for a small app.

The trade-offs: grouping that splits on Node internals, releases tied to git commits unless you configure them, and an AI that guesses when it can't see code. To weigh it against a dedicated error tracker with tracing, read our Sentry vs PostHog comparison.

Choose Raygun if release reviews drive your workflow

  • You resolve bugs against versions. Resolve in next version and a Regressions tab per deployment make each release reviewable.
  • Page speed is a product metric. RUM measures load times and Core Web Vitals across every visitor.
  • You want predictable bills. Fixed tiers with a stated overage rate, and a switch that stops counting a known bug.

The trade-offs: separate applications per tier, no session video, manual source map uploads on the trial, and an APM agent to keep away from crash reporting. Our Sentry vs Raygun comparison puts it next to a tool with stronger tracing.

FAQ

Does Raygun have session replay?

No. Raygun's RUM records each visit as a timeline of page views with load times and errors. PostHog records video with the console and network calls.

Why did PostHog show my releases as git commits?

posthog-cli sourcemap inject picks the release from git unless you pass --release-name and --release-version to it. Passing them only to upload doesn't change the release. Sending $app_version from your SDKs tags events directly.

Can I use Raygun APM and Crash Reporting together on Node.js?

Yes, with one setting. With raygun-apm installed, native errors arrived as "Unknown error" in my test. Setting RAYGUN_APM_CRASH_REPORTING_INTEGRATION=false turns off the bridge that causes it.

Which one is cheaper for a small team?

PostHog. Its free allowance is large enough that a small app may never pay, with errors, replay and logs all included. Raygun has no free plan, and its error tracking starts at $40 a month billed annually.

Final thoughts

PostHog behaved like one product with many tabs, while Raygun behaved like three products sold together. That shaped every result, from one list of errors against two to a trace on the error page against an agent that damaged the error reports.

The real decision is release discipline against breadth. Raygun's version-aware resolve and deployment pages are what a team doing weekly release reviews will miss in PostHog. PostHog's traces, logs and replay are what a small team debugging across tiers will miss in Raygun.

If you pick Raygun for its releases, keep its APM package out of the same Node.js process as its crash reporter.