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

My test app's worst release slowed checkout from about 15 ms to over 4 seconds and started failing card payments. TrackJS's Versions page showed it with the fewest errors of all three releases. Raygun's RUM comparison went further and called it "34.8% faster" than the release before. Both tools were reading real numbers, and both pointed the wrong way.

That shared blind spot says something about each product. Neither measured the one request that broke, so everything else in this comparison is about what they do see.

**TrackJS is a front-end JavaScript error monitor** with a lighter Node.js agent, a telemetry timeline on every error, and a built-in AI Debugger. It bills by page view and doesn't charge for errors.

[ad-logs]

Raygun splits monitoring into three products you buy one by one, for crashes, real users and server performance. Each part of your app, such as the API and the storefront, becomes its own application with its own key and error list.

I put both through the same intentionally broken bookstore in late October 2026. You'll see them weighed on setup, error capture, debugging, the path from browser to server, grouping, real user monitoring, releases and regressions, performance, logs, alerts, AI and pricing.

## TrackJS vs Raygun: Results at a glance

These results come from my Express and Vite setup, with source maps on localhost. A public build, a paid Raygun plan with API tokens, or a CommonJS app could change a few calls.

| Area | Better in my test | Why |
|---|---|---|
| Setup | Mixed | TrackJS's Express handler hung 5xx responses; Raygun's APM package erased error messages |
| Error capture | **TrackJS** | Caught the unhandled rejection that Raygun missed |
| Debugging an error | **Raygun**, narrowly | Source maps that stay applied and server breadcrumbs per request |
| Browser to server | **TrackJS** | Each fetch links to the server error it caused; Raygun can't join its two apps |
| Error grouping | **Raygun**, narrowly | Both split by message text; TrackJS split far more often |
| Real user monitoring | **Raygun** | Web vitals, page and XHR timings, and sessions per user; TrackJS has none |
| Releases and regressions | **Raygun** | Reopened the returning bug and listed it as a regression; TrackJS kept it marked Fixed |
| Performance | **Raygun**, narrowly | Has APM and XHR timings, though neither showed the slow query |
| Logs | Neither | No logs product in either; both keep console lines on errors |
| Alerts | Not compared | No channel connected to either |
| AI-assisted debugging | Not compared | TrackJS's AI Debugger ran; Raygun's MCP server wasn't tested |
| Price | Mixed | Raygun is cheaper for errors billed yearly; TrackJS doesn't bill errors at all |

## How I tested TrackJS and Raygun

My test subject is a small online bookshop that misbehaves on cue. It has an Express API over SQLite, a Vite storefront that routes by hash, a stub price service and a nightly-style report job. Headless Chromium sessions acted as shoppers, so both tools faced the same failures in the same code.

The problems I seeded:

- **Front-end crashes:** a wishlist click that reads from null, and API failures that the storefront reports.
- **Back-end crashes:** an unrecognized coupon at checkout, a lookup of a book that doesn't exist, and an out-of-stock order.
- **A shaky upstream:** the price service sometimes replies 503.
- **Async failures:** a recommendations promise that rejects with no handler, plus a report job that throws.
- **Last-release extras:** a slow book query in checkout and a payment bug, both off until the third version.

### The three versions

| Version | Role in the test |
|---|---|
| 1.0.0 | Installing each tool and studying its first errors |
| 1.1.0 | Checking whether a fixed bug that returns gets flagged |
| 1.2.0 | A faulty deploy that slowed checkout's book lookup and made every fifth payment fail |

Version 1.2.0 is the one to watch. It combined a slowdown with a new error on a single request, the pattern a real bad deploy usually follows.

### SDKs and test limitations

| Platform | TrackJS | Raygun |
|---|---|---|
| Server | `trackjs-node` 1.3.0 | `raygun` 2.2.10 |
| Browser | `trackjs` 3.10.4 | `raygun4js` 3.1.4 |
| Plan | Trial, priced by page views | 14-day trial |

- **Scope:** TrackJS sells browser error monitoring with a Node.js add-on. I judged its tracing and logs gaps as outside its scope, and held it to account for its own features.
- **Counts:** each tool received its own traffic runs, so totals don't line up one to one.
- **Localhost source maps:** TrackJS can only fetch maps from public URLs, so it had manual mode only. Raygun's API uploads need a paid token, so it had manual uploads only.
- **Raygun APM:** the APM profiler wraps `require`, and my app uses ES modules, which limited what its traces could show.
- **No alert channels and no repository:** neither tool had a notifier connected, and neither AI could read my code.

### Terms in each tool

| Concept | TrackJS | Raygun |
|---|---|---|
| A group of errors | Error group | Error group |
| A release | Version | Version, plus a deployment |
| A fixed error | Fixed status label | Resolved |
| Breadcrumbs | Telemetry timeline | Breadcrumbs |
| Where errors live | One application for both sides | One application per part of the app |
| Browser performance | Not offered | Real User Monitoring |

## Setup and onboarding

TrackJS gives you one application for the whole app and two small agents. Raygun asks for one application per part of your stack and sets up one product at a time. Each had a trap in its documented path, and both were serious.

### TrackJS: Simple install, broken Express handler

The browser agent goes in with a script tag or an npm import:

![TrackJS install page with the snippet and onboarding steps](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/a1c9f638-e1a8-4054-f74c-a6affd51b200/orig =1514x737)

Onboarding runs through Agent, Applications, Team and Ignore. The application key fills in from the name as you type, and keys can't be edited later:

![TrackJS application form with a doubled key](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/070d352b-e84a-4b78-b26c-2cb7162dd500/lg2x =1514x737)

My own typing doubled the key here, so the fix was a new application.

The server agent was the real problem. Version 1.3.0 of `trackjs-node` drops whatever options you hand to its Express error handler. Once a route fails with a 5xx, it reports the error and never calls `next()`, so the request hangs with no response. I reproduced it on a bare Express 5 server, then wrapped the handler to pass the error on myself:

```javascript
[label src/monitoring/trackjs.js]
export function afterRoutes(app) {
  const handler = TrackJS.Handlers.expressErrorHandler();
  app.use((err, req, res, next) => {
    let passed = false;
    handler(err, req, res, () => {
      passed = true;
      next(err);
    });
[highlight]
    if (!passed) next(err);
[/highlight]
  });
}
```

The highlighted line is the workaround. Without it, every checkout that failed with a 500 timed out in my test.

### Raygun: One app and one product at a time

Raygun's onboarding sets up one application and one product per pass, and it waits for a first event before letting you continue. My stack became two applications, `monitoring-lab-api` for Crash Reporting and `monitoring-lab-web` for Crash Reporting and RUM, each with its own API key.

Two problems took longer to find:

- **The npm browser package didn't start in a lazily loaded module.** `raygun4js` only reads its settings when the window's `load` event fires, and my module loaded after that, so it sat idle. I queued calls the way the CDN snippet does, then imported the library after load.
- **Installing the APM package broke Crash Reporting.** With `raygun-apm` installed, even with the profiler off, route crashes showed up as "Unknown error", stripped of both message and stack:

![Raygun errors arriving as Unknown error after installing raygun-apm](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/44ed786c-b5a5-41dd-c08d-e753fc28f500/lg1x =1512x800)

The cause is in the packages' own code. The crash reporter loads an APM bridge that replaces `global.Error`, so native `TypeError`s fail `instanceof Error` and are sent empty. Uninstalling `raygun-apm` cured it, and so does the environment variable in the tip below.

<details>
<summary>Source maps and deployments on the trial</summary>

Raygun's source map and deployment APIs need a Personal Access Token, which the trial doesn't allow. So I uploaded each map by hand in the JS Source Map Center and typed a URL label for every file after each build. My first manual deployment also failed with a Raygun 500 page until I filled in only the version.

</details>

> **Worth turning on in Raygun:** if you add APM to a project that already uses Crash Reporting, set `RAYGUN_APM_CRASH_REPORTING_INTEGRATION=false` and check that a native error still arrives with its message.

### Setup comparison

| Capability | TrackJS | Raygun |
|---|---|---|
| Structure | One application for both sides | One application per part of the app |
| Browser install | ✔: script tag or npm | npm import fails in lazy modules |
| Server install | ✘: Express handler hangs 5xx in 1.3.0 | ✔: worked once APM was removed |
| Source maps on localhost | Manual drop only | Manual upload with a label per file |
| Deployments | Not offered | By hand on the trial, API on paid plans |
| Product side effects | Not observed | APM package erases native errors |

**Verdict: Mixed.** Each tool's documented setup broke something important: TrackJS's Express handler hung failing requests, and Raygun's APM package emptied native errors. TrackJS is quicker to install if you patch the handler. Raygun suits teams that want separate apps per service from the start.

## Error capture

Both tools hook uncaught errors in the browser and in Node.js. They split on the failure that no code reported.

### TrackJS: Every planted failure, plus extras

After a clean run, TrackJS held 99 errors in 29 groups:

![TrackJS errors list with Top Errors and Highest Impact panels](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/f631aa17-73b0-49eb-bad1-18c4b30c2100/lg2x =1512x801)

Every failure I planted is there, including the unhandled rejection under the Express entry. TrackJS also adds errors you didn't ask for. It reports every failed fetch as its own Network Error, next to the app's own report of the same failure:

![TrackJS errors list with each checkout failure reported twice](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/56237fa5-b3d7-4a46-9cc4-8e8c4a2d0600/lg2x =1512x801)

It also turns `console.error` lines into errors by default, which gave me a group for "Cannot set headers after they are sent". Expect extra rows until you tune those settings.

### Raygun: Clean groups, one failure missing

Raygun's API application listed five groups:

![Raygun error groups for the API application](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/177ba59c-5e8d-4c7c-f78e-3b8598bedf00/lg1x =1512x744)

The crashes, the 503s, the out-of-stock error and the report job are all there. The unhandled rejection is missing, even with `reportUncaughtExceptions` on. Browser errors went to the separate web application, which listed eight groups of its own.

### Capture comparison

| Capability | TrackJS | Raygun |
|---|---|---|
| Server crashes | ✔: reported | ✔: reported |
| Browser crashes | ✔: reported | ✔: reported |
| Unhandled rejection | ✔: reported | ✘: missing |
| Failed fetches | ✔: automatic Network Errors | Through the app's reports |
| Console errors as errors | ✔: on by default | Not observed |
| One list for both sides | ✔: tagged by side | ✘: separate applications |

**Verdict: TrackJS.** It caught everything, including the rejection Raygun let through. Its defaults also double up browser failures, so a TrackJS list needs some pruning to read cleanly.

## Debugging an error

A good error page shows the failing line and the steps that led to it. The two tools take different routes to that, and source maps decided much of it.

### TrackJS: A rich timeline, maps that don't stick

TrackJS puts a telemetry timeline on every browser error:

![TrackJS browser error with the telemetry timeline](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/f1cb808c-e409-4d2a-783d-ceb54fa59800/orig =1512x801)

Clicks with their element, hash navigations, fetches with status and duration, and the app's console lines sit in one list. An **Errors on Page** strip jumps between all errors from that page load, and **Time On Page** tells you how long the visitor had been there.

Source maps were harder. TrackJS fetches maps from the script's public URL, and on localhost it couldn't:

![TrackJS sourcemap information saying the script isn't public](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/9640467f-1573-436e-9cce-17b22f099600/orig =1512x801)

You can drop a `.map` file onto the stack trace to apply it:

![TrackJS wishlist error after dropping the source map](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/1c3dbc00-c313-4b88-7d7b-370bc5d01600/lg1x =1512x801)

With the map dropped in, the frame becomes line 122 of `pages.js`. The map lives in your browser tab, though, and a refresh brought the minified frames back.

Server errors in TrackJS list a file and line number, with no source and no request body. The telemetry includes this request's steps, but also startup and job console lines from minutes earlier.

### Raygun: Maps that stay, breadcrumbs per request

Raygun took a manual upload per file on the trial:

![Raygun JS Source Map Center with labelled files](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/99190265-e574-41f6-598a-bb7f74c39b00/md2x =1512x800)

Once uploaded, "Re-process this error for Source Maps" fixed the wishlist error for good:

![Raygun browser error mapped to src/pages.js](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/133efeeb-7f19-4d49-a11d-bdda02fd0e00/lg1x =1512x744)

Lines 119 to 125 appear, with the planted-bug comment. On the server, breadcrumbs stayed inside the request:

![Raygun request-scoped breadcrumbs on the coupon error](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/e0321b8b-1aba-4083-a4c0-2f62f7065400/md2x =1512x744)

Only this checkout's two steps appear, with no noise from other shoppers. The stack itself showed `server.js:150` and no code.

### Debugging comparison

| Capability | TrackJS | Raygun |
|---|---|---|
| Browser timeline | ✔: clicks, fetches with timing, console | ✔: clicks, hash changes, XHR |
| Source maps without a public URL | Manual, lost on reload | ✔: manual upload, stays applied |
| Server code lines | ✘: file and line only | ✘: file and line only |
| Server breadcrumbs | Mixed: includes other console history | ✔: scoped to the request |
| Request details | ✘: no body or headers | ✔: HTTP tab |
| Time on page | ✔: shown | ✘: not observed |

**Verdict: Raygun, narrowly.** Its source maps stayed applied and its server breadcrumbs belonged to the request. TrackJS's browser timeline is the better read, so a front-end team might reverse this call.

## From the browser to the server

When a storefront call fails, you want the server error behind it. This is where TrackJS's small Node.js agent pays for itself.

### TrackJS: A link on every request

Each fetch in TrackJS's timeline carries a link to the server errors from the same request:

![TrackJS checkout fetch with the Server Errors Occurred link](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/a2573286-70e5-4676-dc56-60887aa39c00/md2x =1512x801)

The Node.js agent sets a correlation header, and the browser agent records it. Clicking the failing checkout's link opened the server's coupon error:

![TrackJS server coupon error opened from the browser link](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/2a6744b5-9338-419c-bd8d-874b3ce2cd00/lg2x =1512x801)

It's a true join without a tracing product. Because every fetch shows the link, even ones that succeeded, some clicks lead to an empty page.

### Raygun: Two applications, no join

Raygun keeps the storefront and the API in separate applications with separate error lists. A browser `ApiError` and the server crash behind it never link up, and Crash Reporting has no tracing to connect them.

### Browser-to-server comparison

| Capability | TrackJS | Raygun |
|---|---|---|
| Browser request to server error | ✔: correlation link | ✘: not offered |
| Shared error list | ✔: one application | ✘: two applications |
| Timing on the server side | ✘: not recorded | ✘: not recorded |

**Verdict: TrackJS.** It went from a failed fetch to the exception it caused in one click. With Raygun, you match the two by time and guesswork.

[summary]
<iframe width="100%" class="aspect-video h-auto" src="https://www.youtube.com/embed/7tQ7haFmSXI" title="Explore Traces | Better Stack" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

Raygun can't connect its two applications, and TrackJS's link lands on a server error with no timing for the work behind it. A storefront visit in my Better Stack test came out as one timeline covering browser and API alike:

![Better Stack timeline joining storefront and API spans](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/b980fb66-b9a0-438a-2be4-0225195d2300/public =1512x744)

Notice the 30 frontend spans sitting above the 7 backend spans they triggered. A slow or failing step shows its duration on both sides, without opening a second tool.

**[Follow a visit from click to query](https://betterstack.com/tracing)**
[/summary]

## Error grouping

Grouping turns thousands of events into a short list. TrackJS groups by message text. Raygun's Node.js grouping also includes the message, so both split bugs whose messages carry values. They differ in how often.

### TrackJS: A group for every value

TrackJS split anything with a variable in its message:

![TrackJS list showing message-based splits](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/6c47783a-e2bf-4d6a-1c9e-c2a128336b00/public =1512x801)

The out-of-stock error split by book and quantity, and every distinct list of IDs in the tracking URL became a group of its own. On 1.2.0, the payment error went the same way:

![TrackJS payment errors split by amount](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/280ec9e5-a0e6-4c02-8222-ab9bf03ecd00/md2x =1512x801)

Each of the three failed charges got its own server group, and the browser added a fourth. Each had one event, so none of them grew into a trend.

### Raygun: Fewer splits, still some

Raygun split the payment error too, by amount:

![Raygun errors after 1.2.0 with the payment error split](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/5193104c-25f5-443b-9a6d-5863c14ebf00/md1x =1512x744)

It made two groups, one with 8 events, so the larger group still showed a pattern. The 1.2.0 code change also opened duplicate groups for the coupon and out-of-stock errors, and the browser application split one `ApiError` by URL.

### Grouping comparison

| Capability | TrackJS | Raygun |
|---|---|---|
| Grouping key | Message text | Class, stack and message on Node.js |
| New payment bug | ✘: one group per amount | ✘: 2 groups |
| IDs in the message | ✘: one group each | Grouped for the tracking 404 |
| Duplicates after a code change | Not observed | ✘: coupon and out-of-stock split |
| Merging | "Create Group" and grouping rules, not tested | Not tested |

**Verdict: Raygun, narrowly.** Both split real bugs by their values, but TrackJS did it far more often. Raygun suits teams that can live with an occasional duplicate, and TrackJS suits teams willing to write grouping rules early.

[summary]
<iframe width="100%" class="aspect-video h-auto" src="https://www.youtube.com/embed/-26mmryojE4" title="Error tracking | Better Stack" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

TrackJS made one group per failed charge, and Raygun still split the same bug in two. In my Better Stack test, all 10 payment exceptions from 1.2.0 stayed in a single group:

![Better Stack payment error as one group with its source](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/e5e5a3b3-9db0-4323-aa84-fa0088103900/lg2x =1512x744)

Different amounts didn't matter, and the source for line 173 is right on the page. You watch one count climb, and nobody writes grouping rules.

**[Group errors by what broke](https://betterstack.com/error-tracking)**
[/summary]

## Real user monitoring and session replay

Measuring how pages load for real visitors is a paid Raygun product. TrackJS records a little about each page with an error and nothing else. Neither records video replays.

### Raygun: Pages, requests and sessions

Raygun's RUM covers load time and Core Web Vitals:

![Raygun RUM performance tab with web vitals](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/b5ebd5de-809c-40fd-3bb8-774d60f0ee00/lg2x =1512x744)

Its virtual pages and XHR tables show where time goes:

![Raygun most viewed virtual pages and XHR requests](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/32f165cf-b427-4d5a-f409-c19924227600/lg2x =1512x744)

The book pages averaged 1.58 s and the price requests 2.63 s. Raygun collapses `/books/3` into `/books/*`, so finding one slow page means drilling in. Each user's sessions sit on a timeline:

![Raygun RUM session timeline for one user](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/f0e9cb71-0454-462d-a35b-9e0fdd0bfa00/orig =1512x744)

It's a list of page views with timings, without a video.

### TrackJS: Errors only

TrackJS counts a page view each time its agent starts, which in a hash-routed app means once per load. It shows **Time On Page** on errors, and no page timings or web vitals.

### RUM comparison

| Capability | TrackJS | Raygun |
|---|---|---|
| Web vitals | ✘: not offered | ✔: LCP, INP, CLS and more |
| Page load times | ✘: not offered | ✔: per virtual page |
| XHR timings | Per error, in the timeline | ✔: table across requests |
| Sessions per user | ✘: not offered | ✔: timeline per session |
| Session replay | ✘: not offered | ✘: not offered |

**Verdict: Raygun.** It's the only one with real user monitoring. That costs extra, since RUM is billed as its own product.

## Release tracking and regressions

After a deploy, you want new errors flagged and fixed ones caught if they return. TrackJS treats a fix as a label. Raygun treats it as a promise tied to a version.

The difference shows in what can move an error between states:

![Diagram of error states in TrackJS and Raygun and what moves an error between them](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/b1bbf3df-7e65-4b20-016f-9369c3ffe400/lg1x =1512x610)

TrackJS's statuses never change on their own. Raygun reactivates a resolved error when it occurs in a newer version.

### TrackJS: Fixed stays Fixed

TrackJS's **Set Status** menu offers labels:

![TrackJS Set Status menu](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/7a06d318-733e-4e0a-d3f2-9907e869e200/public =1512x801)

I marked the coupon error **Fixed** and shipped it again in 1.1.0. It kept arriving, and it kept the label. The only sign was in its version chart:

![TrackJS coupon error versions chart with 1.1.0 in red](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/30918f45-04c6-495b-4f02-2dd102fdf900/public =1512x801)

The red 1.1.0 bar and "Versions Impacted 2" show the return, if you open the group. The dashboard's **New Errors** list meanwhile filled with message variants:

![TrackJS dashboard New Errors after 1.1.0](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/e229abb7-f150-4676-a2cd-4344a640ba00/lg1x =1512x801)

Nothing there pointed at the returning coupon error.

### Raygun: Resolved in the next version, reopened on return

Raygun offers several ways to resolve:

![Raygun resolve options](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/58faad20-65dd-47e1-43d9-a373c4079f00/md1x =1512x800)

**Resolve in next version** keeps older versions quiet and reactivates the error if a newer one reports it:

![Raygun Resolve in next version dialog](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/c8fb7442-3eef-442a-e848-b8ee10252900/lg1x =1512x800)

Its "Discard future occurrences" checkbox is ticked by default. When 1.1.0 brought the bug back, the deployment page sorted it into **Regressions**:

![Raygun 1.1.0 deployment with the Regressions tab](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/1eec3e22-6d7f-4c1e-546f-ecf853d63600/lg2x =1512x744)

That's a release view that names the returning bug.

### The returning bug in both tools

Here's the coupon error after 1.1.0 in each tool, trimmed to the parts that matter:

![The returning coupon error in TrackJS and Raygun with numbered markers](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/2fb7a1b3-7c23-4a93-674e-823a74260800/md2x =1512x381)

In TrackJS, the count at ① kept climbing while the label at ② still says **Fixed**. In Raygun, the activity feed records "Error reoccurred" at ① after my resolve at ②.

> **Worth turning on in TrackJS:** enable **New Errors** and **Error Rate Increases** notifications, and check the version chart on any group you mark **Fixed**, because the label never changes by itself.
>
> **Worth turning on in Raygun:** resolve with **Resolve in next version** and create a deployment for every release, so returning bugs land in the **Regressions** tab.

### Release comparison

| Capability | TrackJS | Raygun |
|---|---|---|
| Mark fixed for a version | ✘: label only | ✔: in a version or the next one |
| Reopens a returning bug | ✘: stays Fixed | ✔: reactivates |
| Reopen recorded | ✘: version chart only | ✔: "Error reoccurred" in activity |
| Release page | Versions page, counts only | ✔: New, Regressions, Still occurring |
| Deployments | ✘: not offered | ✔: manual, or API on paid plans |
| Reopen shown in the list | ✘: none | ✘: row shows Active |

**Verdict: Raygun.** It reopened the bug, logged why, and listed it under the release that brought it back. TrackJS records your intent and nothing more, so a Fixed bug can return unnoticed.

[summary]
<iframe width="100%" class="aspect-video h-auto" src="https://www.youtube.com/embed/E8JQPRVR20E" title="On-call Overview | Better Stack" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

TrackJS kept the returning bug labelled Fixed, and Raygun logged the reopen in an activity feed that the error list doesn't show. Better Stack got the same 1.1.0 release in my test and flagged the coupon error in the list itself, with a red "Reoccurred" status:

![Better Stack error list with the Reoccurred status](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/ff9ed40b-81f9-4dea-bca1-9d2fdeccd200/lg1x =1512x744)

Only the returning error changed, and its activity feed records the reopen. Better Stack has no deployment records like Raygun's, but the regression shows at a glance.

**[Catch bugs that come back](https://betterstack.com/error-tracking)**
[/summary]

## Performance monitoring

A bad release usually shows first as slow requests. TrackJS doesn't measure performance. Raygun has RUM for the browser and APM for the server, and in this test both missed the slow query.

### TrackJS: A duration inside one timeline

The only sign of the slowdown was a network entry in a failing checkout's timeline:

![TrackJS failing checkout fetch taking 4073 milliseconds](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/c52f1902-1dd7-47e5-96ed-c0e698a5ab00/orig =1512x801)

That checkout request ran for 4,073 ms; on the first release, the same call finished in roughly 15 ms. Successful slow checkouts left no trace, because TrackJS records nothing without an error.

### Raygun: APM that couldn't see the app

Raygun's APM needs a separate agent next to your app. Its overview showed request timings:

![Raygun APM overview](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/cb6735fc-87bd-4789-afe8-3e237f58c200/md2x =1512x800)

The breakdown never got further than that. Slowest methods and slowest queries were empty, SQLite isn't supported, and the profiler's hooks miss ES module imports:

![Raygun APM flame chart showing only idle time and garbage collection](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/95169f4a-b221-4c97-d9f3-92f221144900/orig =1512x800)

The real wait shows as "(idle)". In RUM, the `/checkout` XHR averaged 438.95 ms across all releases, with no working filter for 1.2.0, and RUM Compare looked at page loads only:

![Raygun RUM Compare calling 1.2.0 faster](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/633d1236-219f-4c23-b4f6-2da7434dfc00/md2x =1512x744)

Its verdict, "1.2.0 is running 34.8% faster", came from page loads that the bad release never touched.

### What each release view said about 1.2.0

Both tools have a page meant to tell you how a release went:

![Bar charts of TrackJS errors per version and Raygun median page load per version](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/d9908090-5cfc-4cca-ec18-b06b1d37d100/lg2x =1512x744)

TrackJS counted fewer errors on 1.2.0 because fewer checkouts got through. Raygun measured page loads, which didn't change. Neither number covered the checkout request.

### Performance comparison

| Capability | TrackJS | Raygun |
|---|---|---|
| Request timing | ✘: not offered | ✔: APM, separate agent |
| App code in traces | ✘: not offered | ✘: ES modules not instrumented |
| Database queries | ✘: not offered | ✘: SQLite not supported |
| XHR timing | Per failing request | ✔: averages across releases |
| Release comparison | Error counts only | Page loads only |
| Found the slow query | ✘: no | ✘: no |

**Verdict: Raygun, narrowly.** It has the tools, and its XHR table did show checkout getting slower overall. In my ES module app, though, neither product pointed at the cause, and its own release comparison praised the bad deploy.

## Logs and events

Neither tool stores logs. TrackJS records console output in each error's timeline. Raygun keeps breadcrumbs, including the app's own, on each error.

On 1.2.0, TrackJS's server timeline did hold my app's own warning, `[warn] slow query: SELECT book for checkout`, 1.52 s before the payment error. That's the closest either tool came to the cause.

| Capability | TrackJS | Raygun |
|---|---|---|
| Logs product | ✘: not offered | ✘: not offered |
| Console lines on errors | ✔: in the timeline | Through breadcrumbs |
| Search across logs | ✘: not offered | ✘: not offered |

**Verdict: Neither.** You'll need a separate log store with either tool.

[summary]
<iframe width="100%" class="aspect-video h-auto" src="https://www.youtube.com/embed/XJv7ON314k4" title="Live Tail Overview | Better Stack" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

The slow-query warning existed only as one console line inside one TrackJS error, and Raygun had no logs at all. Better Stack handled the same failed checkout in my test, and its log link narrowed Live tail to that one request:

![Better Stack Live tail filtered to one failing checkout](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/0bd2859e-1627-424b-5fcb-b7bb7027c200/public =1512x744)

The failed checkout line sits next to the slow-query warning from the same request. The cause is one click from the error, in a log store you can also search later.

**[Search the logs behind every error](https://betterstack.com/log-management)**
[/summary]

## Alerts

TrackJS sends **New Errors**, **Trending Errors** and **Error Rate Increases** alerts, plus daily and weekly summaries, by email, Slack or Teams:

![TrackJS notification settings](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/485f93e6-4550-4dbd-16e7-c638d91d3100/lg2x =1512x801)

None of its alerts covers a Fixed error that returns, since **New Errors** keys on message text. Raygun's applications default to new-error alerts and daily summaries. I connected no channel to either, so I can't say how the alerts read.

**Verdict: Not compared.** Neither tool sent me an alert during the test.

## AI-assisted debugging

TrackJS has an AI Debugger on every error. Raygun offers a remote MCP server for outside assistants, and its pricing page lists AI error resolution on Crash Reporting plans. I tested only TrackJS's, so this section isn't a head-to-head.

### TrackJS: Careful, and clear about its limits

Opening the AI Debugger tab starts an analysis, with sanitized error data sent to OpenAI by default. On the payment error from 1.2.0, it took about 20 seconds:

![TrackJS AI Debugger likely cause for the payment error](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/1534b070-871a-4838-499e-a12bc4b8ad00/orig =1512x801)

It placed the failure at `server.js:173` on 1.2.0 and ruled out a declined card or a bad coupon. It didn't find the every-fifth-charge counter, because it had no code to read. Its fix list was more interesting:

![TrackJS AI Debugger fix suggestions](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/b4f46882-28d4-4a96-4842-07bab6d4cf00/lg2x =1512x801)

Its last suggestion treated the slow book lookup as a separate latency problem, so it didn't blame one issue for the other. On the wishlist and coupon errors, it gave hedged but reasonable hypotheses and said plainly that it lacked the source to decide.

### Raygun: An MCP server, untested

Raygun has no assistant inside its interface. Its MCP server lets tools like Claude Code or Cursor investigate errors, deployments, sessions and APM data after an OAuth sign-in. I didn't test it.

### AI comparison

| Capability | TrackJS | Raygun |
|---|---|---|
| Assistant in the product | ✔: AI Debugger, tested | ✘: not observed in the app |
| Code access | ✘: error data only | Not tested |
| Kept the slowdown separate | ✔: yes | Not tested |
| MCP server | Not observed | ✔: available, not tested |
| Data sharing | Sanitized error data to OpenAI, can be disabled | Not tested |

**Verdict: Not compared.** TrackJS's AI Debugger was careful and useful within its limits. I didn't run Raygun's option, so there's no fair match.

[summary]
<iframe width="100%" class="aspect-video h-auto" src="https://www.youtube.com/embed/n6TtDk8ITgc" title="AI SRE Demo | Better Stack" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

TrackJS's AI Debugger saw one error at a time and missed the payment counter, and Raygun leaves the work to an outside assistant. Better Stack's AI SRE got a broader question from me, comparing the two latest releases, with no code connected:

![Better Stack AI SRE comparing 1.2.0 with 1.1.0](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/9c18a3bf-a83b-4e4c-2b40-adaf417dfc00/md2x =1512x744)

It found the one slow query among fast ones and cleared the database host, then traced the card failures to 1.2.0 alone, at 10 of 48 charges. It took about four minutes and $0.49, far slower than TrackJS's 20 seconds, and it explained the whole release.

**[Ask AI SRE about your last release](https://betterstack.com/ai-sre)**
[/summary]

## Pricing

TrackJS charges by page view, keeps a set number of errors per minute, and never bills for errors. Raygun bills each product separately: Crash Reporting by errors, RUM by sessions and APM by traces.

I read TrackJS's and Raygun's pricing pages on November 6, 2026. Prices change, so confirm them before you sign up.

### Free plans and trials

| Item | TrackJS | Raygun |
|---|---|---|
| Free plan | ✘: none | ✘: none |
| Trial | Free trial, length not stated on the page | 14 days on every product |
| My trial | 1 million page views | Crash Reporting, RUM and APM |
| API access on trial | Not checked | ✘: Personal Access Token blocked |

TrackJS's billing page showed my trial terms:

![TrackJS billing page during the trial](https://imagedelivery.net/xZXo0QFi-1_4Zimer-T0XQ/4899d261-57d8-4c14-f70a-4ac27fce2100/lg2x =907x447)

The trial ran free until November 11, with a **Subscribe** button and nothing else to configure.

### Entry-level paid plans

| Item | TrackJS Starter | TrackJS Professional | Raygun Crash Reporting Basic |
|---|---|---|---|
| Monthly | $49 | $99 | $60 |
| Yearly, per month | $45 | $91 | $40 |
| Volume | 100,000 page views | 1,000,000 page views | 100,000 errors |
| Errors kept | 20 a minute | 60 a minute | Billed per error |
| Retention | 10 days | 15 days | 180 days |
| Applications | 1 | 5 | Not stated |
| Users | Unlimited | Unlimited | Unlimited |

Raygun RUM Basic and APM Basic each cost $120 a month, or $80 a month yearly, for 100,000 sessions or traces.

### What costs extra

| Need | TrackJS | Raygun |
|---|---|---|
| More volume | A bigger plan; limits are soft | $0.001 per extra error |
| Real user monitoring | ✘: not offered | Separate product from $80 a month yearly |
| Server performance | ✘: not offered | APM from $80 a month yearly |
| Usage caps | Errors past the per-minute limit aren't kept | Add-on, price not listed |

### Comparing the actual cost

For error tracking alone, billed yearly, Raygun's Crash Reporting Basic is cheaper at $40 a month against TrackJS Starter's $45, and it keeps errors for 180 days against TrackJS's 10. TrackJS's bill doesn't move when a release throws thousands of errors, though, because it charges for page views and keeps 20 errors a minute.

The gap widens once you want more than errors. Raygun with RUM costs $120 a month yearly, and adding APM brings it to $200. TrackJS has nothing to add, so a TrackJS team buys performance monitoring elsewhere. Our [Rollbar vs Raygun comparison](https://betterstack.com/community/comparisons/rollbar-vs-raygun/) looks at the same Raygun bill against a cheaper error tracker.

**Verdict: Mixed.** Raygun is cheaper per error with longer retention. TrackJS is the predictable bill for a busy front end that throws a lot.

## Full feature comparison

| Feature | TrackJS | Raygun |
|---|---|---|
| Structure | One application, two agents | One application per part of the app |
| Unhandled rejections | ✔: reported | ✘: missed |
| Automatic network errors | ✔: on by default | ✘: not observed |
| Source maps on localhost | Manual, not saved | Manual upload, saved |
| Browser timeline | ✔: clicks, fetches, console | ✔: breadcrumbs |
| Browser to server link | ✔: correlation link | ✘: not offered |
| Grouping | Message text | Class, stack and message |
| Real user monitoring | ✘: not offered | ✔: separate product |
| Resolve in next version | ✘: label only | ✔: offered |
| Regressions view | ✘: not offered | ✔: per deployment |
| APM | ✘: not offered | ✔: separate agent, limited with ESM |
| Logs | ✘: console telemetry only | ✘: not offered |
| AI | AI Debugger on every error | MCP server, not tested |
| Free plan | ✘: trial only | ✘: trial only |

## Which should you choose?

Decide whether you need one focused tool for the browser or a broader set you'll pay for piece by piece.

### Choose TrackJS if the front end is where things break

TrackJS reported each planted failure, linked each failed fetch to the server error behind it, and put a detailed timeline on every error. Its AI Debugger was careful, and its page-view pricing stays flat however many errors a release throws.

The gaps are real. Its Express handler needs a workaround, Fixed means nothing if a bug returns, message grouping splits bugs by their values, and it measures no performance. For TrackJS against a broader platform, see our [Sentry vs TrackJS comparison](https://betterstack.com/community/comparisons/sentry-vs-trackjs/).

### Choose Raygun if you want release tracking and real user monitoring

Raygun reopened the returning bug and listed it under the release that caused it. Its source maps stay applied, its server breadcrumbs belong to the request, and RUM shows page and request timings across your users.

It's also fiddly. Each part of your app is a separate application with no link between them, the trial blocks API automation, and installing APM broke error reporting until I disabled its integration. For Raygun against another all-round tracker, read our [Raygun vs Honeybadger comparison](https://betterstack.com/community/comparisons/raygun-vs-honeybadger/).

## FAQ

### Does TrackJS monitor Node.js servers?

Yes, with the `trackjs-node` agent. Wrap its Express handler as shown in the setup section, since version 1.3.0 leaves failed requests without a response.

### Does Raygun have session replay?

No. Raygun's RUM shows each session as a timeline of page views and timings, without a video recording.

### Which tool links browser errors to server errors?

TrackJS. Each fetch in its timeline links to the server errors from the same request. Raygun keeps the two in separate applications with no link.

### Is Raygun cheaper than TrackJS?

For errors alone on yearly billing, yes: $40 a month for Raygun Crash Reporting against $45 for TrackJS Starter. Adding Raygun's RUM or APM costs $80 a month each on yearly billing.

## Final thoughts

The choice is between a sharp tool and a broad kit. TrackJS sees everything that happens in the browser and connects it to the server, but a Fixed label in TrackJS is only a hope. Raygun watches more of the stack and remembers what you fixed, at the cost of separate apps, separate bills and setup traps.

Neither one caught the slow query that made 1.2.0 a bad release, and both release views told me it was fine. Whichever you pick, **don't let its release page be the last thing you check** after a deploy.