Sentry vs BugSnag: An Error Monitoring comparison for 2026

Stanley Ulili
Updated on October 26, 2026

Sentry and BugSnag can both tell you when your application breaks, but finding an error is only part of debugging it. You also need to understand what caused it, who was affected, whether a recent deployment introduced it, and whether a bug you thought was fixed has returned.

I tested both platforms using the same Node.js bookstore application, deliberately introducing backend exceptions, failed requests, and recurring errors. I also tested Sentry's browser monitoring, distributed tracing, session replay, and performance tools to see how much additional debugging context they provide.

Both tools caught all six backend errors and grouped them correctly. The differences became clearer when I investigated those errors and tracked them across releases. Sentry displayed the failing source code alongside traces and logs, while BugSnag offered a more focused error investigation workflow with searchable breadcrumbs, correlated events, and release-aware resolution.

One particularly useful difference emerged when I marked an error as fixed and deliberately shipped it again without a fix. Both platforms reopened the error, but Sentry marked it as "Regressed" directly in the issue list, while BugSnag recorded the reopening inside the error's activity history.

Sentry also provided broader performance monitoring and AI-assisted debugging, although its AI agent misidentified the cause of a slowdown in my test. BugSnag focused on error tracking and release stability, with additional OpenTelemetry instrumentation required for performance monitoring.

This hands-on comparison covers setup, error capture, debugging, grouping, search and triage, session replay, release tracking, performance, logs, alerts, AI capabilities, and pricing, using screenshots and results from my October 2026 tests.

Sentry vs BugSnag: Results at a glance

Each verdict reflects my Express app and how I configured it, so read the table as one test's results.

Area Better in my test Why
Setup Sentry, narrowly One project took both SDKs, with tracing, logs and profiling switched on in the snippet
Error capture Tie Both caught all six server bugs as six separate groups
Debugging Sentry Source lines inline on server frames; BugSnag showed file and line only
Error grouping Tie on 1.0.0 and 1.1.0 Both kept every bug apart; only Sentry ran the 1.2.0 release
Search and triage Mixed Sentry has priority and merge; BugSnag has breadcrumb search and version-tied fixes
Session replay and RUM Sentry Replay with an AI summary; BugSnag's browser SDK not tested
Release tracking Sentry A Regressed label in the list, on the issue and in a release tab
Release stability Tie Both track sessions per release with no extra setup
Performance Sentry Traces and profiles from the same SDK; BugSnag's OpenTelemetry route not tested
Logs and metrics Sentry BugSnag offers neither
Uptime and alerts Sentry on availability Uptime and cron monitors, and an alert that fired; BugSnag alerts not tested
AI-assisted debugging Not compared Seer was tested; Fix with MCP was not
Starting price Mixed BugSnag's free plan has more events; Sentry publishes its paid prices

How I tested Sentry and BugSnag

My test app, monitoring-lab, is a deliberately broken bookstore. It has an Express 5 API backed by SQLite, a storefront built with Vite, a fake upstream that serves prices, and a sales report job that runs once a minute. Every monitoring tool plugs into the same adapter functions, so each one receives the same failures from the same code.

The seeded problems fall into these groups:

  • Server errors: a TypeError reading title when a book ID doesn't exist, a TypeError reading discount when a coupon code is unknown, a handled OutOfStockError, an UpstreamError when the price service returns 503, an unhandled promise rejection from a recommendation call, and a sales report job that fails on every run.
  • Browser errors: a broken wishlist button that reads items from undefined, and ApiErrors thrown when API requests fail.
  • Slow paths: a CPU-heavy /search that takes about 2 seconds, and a price lookup that waits 1 to 3.5 seconds on its upstream.
  • Release problems: a resolved bug shipped again unfixed, and a bad deploy with a slow database query and a new payment error.

A traffic script plays three shoppers, alice, bob and carol, through the API, plus headless Chromium sessions for the storefront.

The three releases

Release What I tested
1.0.0 Setup, capture of the six server bugs, stack traces, breadcrumbs, users, search, triage, traces, logs and alerts; for Sentry, browser errors, source maps and replay too
1.1.0 The coupon error marked resolved on 1.0.0, then shipped again unfixed
1.2.0 A bad deploy: a slow SELECT book for checkout query and a PaymentGatewayError on every fifth payment; Sentry only

The coupon bug is the one to follow. It's the TypeError reading discount that fires when a shopper sends a code the store doesn't know.

The bad deploy mattered because it causes two different problems at once. One throws a new exception, which an error tracker should catch. The other slows checkout without throwing anything, which only tracing or logs can expose.

SDKs and test limitations

Platform SDKs
Sentry @sentry/node 11.8.0 and @sentry/profiling-node 11.8.0 on the server, @sentry/browser 11.8.0 in the storefront
BugSnag @bugsnag/js and the @bugsnag/plugin-express middleware for the API

Keep these limits in mind as you read:

  • Both ran on 14-day trials. Neither asked me for a card.
  • Each tool got its own traffic run. The failure scenarios matched, yet random timing means the event totals won't line up one to one, so compare counts inside a tool and never across the two.
  • Some BugSnag features weren't tested. I didn't run its browser SDK, its OpenTelemetry performance monitoring, the 1.2.0 release or "Fix with MCP". Rows for those say "Not tested", and none of them counts against BugSnag.
  • Seer had my repository. I connected GitHub before running Sentry's AI, which changes what it can see.
  • Only Node.js and Express were tested. Grouping and SDK behavior can differ in other languages and frameworks.

Setup and onboarding

Both tools got errors flowing in a few minutes. The differences are in what each one turns on for you and what it asks you to connect.

Sentry: One project for both sides, with a repo step worth keeping

Sentry started me on a 14-day Business Plan Trial with no card. The first onboarding screen pushes you toward setting things up through a coding agent:

Sentry onboarding offering setup through a coding agent

You can follow the agent route or copy the snippets yourself, which is what I did.

A later step asks you to connect your code:

Sentry onboarding step to connect a code repository

I skipped "Connect your code" at first, and it cost me later. Seer refused to run, and every release showed 0 commits until I linked the repository.

When I created the project with GitHub connected, Sentry detected monitoring-lab and offered both Express and Browser JavaScript. One project took both SDKs, so the platform choice only changed which snippet I saw first.

The setup page also asks what you want to track:

Sentry onboarding choices for errors, tracing, profiling, logs and metrics

Errors, logs, metrics, tracing and profiling are all ticked by default, and the generated snippet already holds your DSN. Profiling needs one extra package, @sentry/profiling-node.

BugSnag: Four guided steps that start with where your app runs

BugSnag's onboarding has four steps, from a welcome screen through creating the project and inviting teammates to the integration itself.

BugSnag welcome screen at the start of onboarding

It opens by asking where your application runs, and the choices cover mobile, browser, server, desktop, TV and console. That ordering tells you where BugSnag's roots are, and server support sits beside the mobile options.

The Express integration page shows the install command, then Bugsnag.start with your API key. The request handler has to be the first middleware and the error handler goes after your routes, or errors from early middleware slip past.

The same page promises that server performance works with OpenTelemetry SDKs. That's accurate, but the BugSnag SDK doesn't include tracing, so performance is a second setup job.

Once traffic arrived, the project overview filled in:

BugSnag project overview with session stability and performance monitors

Session stability read 83.103% across 290 sessions with no extra code, because the Express plugin counts one session per request. Look at the two performance monitors, "App starts" and "Core network endpoints": both say "Alerting" before any performance data existed, which is confusing on your first day.

What each SDK gives you

What the SDK gives you Sentry BugSnag
Error capture in Express ✔: error handler after the routes ✔: request handler first, error handler last
User on each error ✔: setUser ✔: setUser
Breadcrumbs ✔: addBreadcrumb ✔: leaveBreadcrumb
Custom metadata ✔: contexts panel ✔: its own tab on the event
Sessions for release health ✔: automatic ✔: automatic, one per request
Custom spans ✔: startSpan ✘: OpenTelemetry instead
Logs and metrics ✔: logger and metrics APIs ✘: not offered
Browser and server in one project ✔: one DSN for both Not tested

Setup comparison

Area Sentry BugSnag
Trial 14-day Business trial, no card 14-day trial, no card
Onboarding style Coding agent or snippets Four guided steps
Defaults Errors, logs, metrics, tracing and profiling Errors and sessions
Repository step Needed for Seer and commits Source control links offered later
First-day surprise Skipping the repo blocked Seer Performance monitors alerting with no data

Verdict: Sentry, narrowly. It switched on more of the product from one snippet and took both sides of the app in one project. BugSnag's guided steps were clear, and its sessions worked with no extra code.

Error capture

Both tools received the six server bugs, and both turned them into six groups. That includes the two TypeErrors, which come from similar property reads in different routes.

Sentry: Six server issues, plus the browser in the same list

Sentry's issue list held the six server bugs:

Sentry issues list with six server issues

The columns read "Events, Users, Priority, Assignee", and a red "Unhandled" label marks the crashes. In this window the coupon error had 9 events from 3 users and the title error had 10.

With the browser SDK sending too, that one project grew to 11 issues, five of them from the storefront:

Sentry issues list with browser and server issues and replay counts

Each row also shows how many replays it has, and the wishlist error had 7. The broken cover image on one book page never became an issue, and it only surfaced later inside a replay.

Sentry's event counts came with a catch. The app wrote more failure log lines than Sentry stored events, and Stats showed where the rest went:

Sentry stats showing client-discarded events

The tooltip for that hour shows 54 events accepted and 9 discarded on the client by the event processor. In that run, the title bug logged 14 failures and Sentry kept 10 events, which fits the SDK dropping identical errors that arrive back to back.

BugSnag: Six errors with a badge on every row

BugSnag's inbox also listed six errors for six bugs:

BugSnag inbox with six errors and handled or unhandled badges

Each row carries a colored dot and a handled or unhandled badge, so OutOfStockError and the sales report job stand out as handled at a glance. The title error sits at server.js:38 with 20 events, and the coupon error at server.js:81 with 13 events from 3 users.

The sidebar pre-sorts the inbox into views, among them "Introduced Today", "For review", "Fixed", "Snoozed" and "Ignored". You get a working triage queue before you type a single filter.

BugSnag has no logs of its own, so I couldn't check its counts from inside the product. If you rank bugs by event volume, compare either tool against your application logs first.

Error capture comparison

Test Sentry BugSnag
Missing book TypeError ✔: own issue ✔: own error
Coupon TypeError ✔: own issue ✔: own error
Handled OutOfStockError ✔: own issue ✔: own error, handled badge
Upstream 503 ✔: own issue ✔: own error
Unhandled promise rejection ✔: own issue ✔: own error
Failing background job ✔: own issue ✔: own error, handled badge
Browser errors ✔: five issues in the same project Not tested
Count check against logs Dedupe dropped repeated events Not possible inside BugSnag

Verdict: Tie. Both caught every server bug and kept each one apart. BugSnag's badges make severity easier to scan, and Sentry's browser capture isn't a point against BugSnag, because I didn't test BugSnag's browser SDK.

Debugging an error

An error page earns its keep by telling you why the error happened. I compared stack traces, breadcrumbs, user context, custom metadata and the unhandled rejection in both tools.

Sentry: Source lines on the frame, and a path across the stack

Sentry showed the crashing server frame with the code around it, read from files on disk, before I'd connected any repository:

Sentry server frame with source lines and hidden framework frames

server.js:81:45 is marked "In App" with lines 76 to 86 shown, and eight framework frames sit collapsed under "Hide 8 frames". You can read the bad property access without leaving the browser.

The breadcrumbs sit above the trace as a timeline:

Sentry breadcrumbs timeline for a failed checkout

"checkout started" carries the coupon BLACKFRIDAY, and "book found" follows a millisecond later, right before the exception. Console lines from the sales report job also appear further down, so the timeline isn't limited to the one request.

Further down the same issue, Sentry adds related data inline:

Sentry coupon issue showing logs, a trace preview and the request body

The "Logs" block shows "POST /checkout failed", the Trace Preview lists the db.query span at 0.26 ms, and the HTTP Request block holds the JSON body the shopper sent. User email appears as a tag and in a User context, and custom data lands in its own "details" panel.

One oddity: the user tag drawer showed bob@example.com for an event that only carried an IP address.

The unhandled rejection came through with its mechanism named:

Sentry unhandled promise rejection with its mechanism

The tag reads auto.node.onunhandledrejection, and the frame points at server.js:144:9 in loadRecommendations, with the line shown.

The storefront errors needed source maps, which I uploaded with sentry-cli. After that, the wishlist crash pointed into the original file:

Sentry browser error with a source-mapped frame

Line 122 of src/pages.js is highlighted, the one calling wishlist.items.push(book.id);. A "Set up Code Mapping" prompt sits on the frame, and it depends on the repository being linked.

The browser error's header and breadcrumbs tell the click story:

Sentry browser error header with breadcrumbs and Seer sidebar

Read top to bottom, it goes from a fetch of /books/2 to a click identified by its selector, then the app's "add to wishlist clicked" crumb, then the crash. The sidebar on the right asks you to finish configuring Seer.

The most useful link in Sentry runs from the browser to the server. On the storefront's failed checkout, the Trace Preview names the backend error that caused it:

Sentry storefront ApiError naming the server TypeError from its trace

"1 other issue appears in this trace" lists the coupon TypeError, and the backend issue links back the other way. That's one click from the symptom a user saw to the line that broke.

The full trace shows both sides in one waterfall:

Sentry trace from the browser click to the database query

It runs from navigation through the "place order" click, the browser's http.client call and the server's handler down to db.query, 12 spans in 64.90 ms. Web vitals sit as chips in the header.

BugSnag: Clean tabs, searchable breadcrumbs and correlated events

BugSnag's stack trace for the title error shows frames without source:

BugSnag stack trace showing frames only

server.js:38:45 leads, followed by the Express router frames and a "Raw view" toggle. To read the code, you'd connect source control or open your editor.

Breadcrumbs are where BugSnag holds its own. Its tab on the coupon error has a type filter and a search box:

BugSnag breadcrumbs timeline with type filter and search

"Error Occurred" sits above the manual "book found" crumb, which carries bookId 3, the title and stock 25. On a long timeline, the search box saves you scrolling.

The user gets a tab of its own:

BugSnag user tab on the coupon error

Both the email and the ID read carol@example.com, separated from the request and device data. The title route set no user or breadcrumbs, so those tabs don't appear on its events at all.

Custom metadata from a handled error lands in its own tab, too:

BugSnag DETAILS tab on the handled OutOfStockError

The "DETAILS" tab shows bookId 7, alice@example.com and quantity 1, which is exactly what the code attached. The event's other tabs include App, Device, Request and Trace.

The newest of those tabs, Correlated events, looks sideways at the same shopper:

BugSnag correlated events from the same user and session

On carol's coupon error, it listed her OutOfStockErrors from the same session. That's useful when one user hits several bugs in a row, and I didn't find a Sentry tab that does the same.

The unhandled rejection arrived with one frame:

BugSnag unhandled rejection with a single frame

server.js:144:9 loadRecommendations is marked unhandled, which points you at the same function Sentry named. The sidebar also offers "Create or link an issue" for your tracker.

Debugging comparison

Capability Sentry BugSnag
Source lines on server frames ✔: 11 lines inline ✘: file and line only
Browser source maps ✔: uploaded with sentry-cli Not tested
Breadcrumbs ✔: timeline ✔: timeline with search and type filter
User ✔: tag and User context ✔: own tab
Custom metadata ✔: own panel ✔: own tab
Related data on the error ✔: logs, trace and request body ✔: correlated events by user and session
Unhandled rejection ✔: mechanism and frame ✔: one frame, unhandled
Browser error linked to backend error ✔: through the shared trace Not tested

Verdict: Sentry. Inline source on server frames saved a trip to the editor on every error, and the trace link from browser to backend answered "why" in one click. BugSnag's breadcrumb search and correlated events were the better tools for reading one user's bad session.

Error grouping

Grouping decides how many issues land in your list. If it merges too much, separate bugs hide inside one row, and if it splits too much, one bug fills the list with copies.

Sentry: Clean on the first two releases, two copies after the bad deploy

On 1.0.0 and 1.1.0, Sentry kept all six server bugs apart, with the two TypeErrors as their own issues. The bad deploy in 1.2.0 changed the checkout code, and the list changed with it:

Sentry issues list after release 1.2.0 with new and duplicate groups

The new PaymentGatewayError arrived as one issue with 13 events across changing amounts. Next to it, a second "TypeError reading 'discount'" and a second OutOfStockError appeared, because the new checkout code shifted their stack frames.

The browser side went the other way. The storefront's "POST /checkout failed with 500" group is keyed on the browser stack, so 1.2.0's payment failures landed in the group the coupon bug had opened, and the row now carried the payment message as its title.

You can merge the copies from the bulk bar, but you have to spot them first.

BugSnag: Six bugs, six groups, with grouping rules you can change

BugSnag labelled each of its six errors "Default grouping" and kept the two TypeErrors apart by location. Its project settings let you switch the rule:

BugSnag project settings with grouping options and integrations

"Group by error class" and "Group by error context" sit next to the integrations list. Those are handy if your messages carry IDs or amounts that would otherwise split a group.

I didn't run 1.2.0 through BugSnag, so I can't say how it would have handled the shifted checkout stack.

Merging too much is the other way grouping fails, and it's worth checking with your own errors before you trust either default.

Error grouping comparison

Test Sentry BugSnag
Six server bugs on 1.0.0 ✔: six issues ✔: six errors
The two TypeErrors ✔: kept apart ✔: kept apart
New payment error with changing amounts ✔: one issue Not tested
Existing errors after the 1.2.0 code change ✘: two duplicate groups Not tested
Browser failures from one helper ✘: payment errors joined the coupon group Not tested
Grouping controls Merge in the bulk bar Group by error class or context

Verdict: Tie on the releases both tools ran. Each one kept every bug apart on 1.0.0 and 1.1.0. Sentry's copies after 1.2.0 are worth knowing about, but they don't make BugSnag the winner, since BugSnag never saw that release.

Search and triage

Both tools let you filter the list, assign owners, snooze noise and comment. They differ in how much structure sits around the error.

Sentry: Typed queries, priority and merge

I asked Sentry for bob's checkout errors on 1.0.0 with a typed query:

 
release:monitoring-lab@1.0.0 user.email:bob@example.com url:*checkout* environment:development

Sentry issues filtered by user, environment, release and URL

The four chips returned two issues, and each row shows bob's share against the total, "1 / 9" on the coupon error and "6 / 15" on OutOfStockError.

Archiving offers five conditions:

Sentry archive options with five conditions

"Until escalating", "Forever", "For...", "Until this occurs again..." and "Until this affects an additional..." cover most ways you'd want to park an issue. The bulk bar adds Resolve, Archive, Merge and Set Priority, and each issue has a priority of high, medium or low.

BugSnag: Structured filters and four snooze rules

BugSnag's filter bar builds chips from structured fields:

BugSnag inbox filtered to bob@example.com

Combining userEmail:bob@example.com and status:open also found two errors, the coupon error with 3 events and OutOfStockError with 4.

Snooze has four rules:

BugSnag snooze conditions

You can wake an error when it occurs again, occurs again after a time, occurs a set number of times, or reaches more users. The toolbar beside it holds Assign, Mark as fixed, Fix with MCP, Snooze, Ignore and Comments & Activity.

Search and triage comparison

Capability Sentry BugSnag
Filter by user ✔: user.email ✔: userEmail
Filter by release and stage ✔: release and environment ✔: release and stage pickers
Search inside breadcrumbs ✘: not on the issue page ✔: breadcrumb search box
Snooze or archive ✔: five conditions ✔: four conditions
Priority field ✔: high, medium, low ✘: not on the error
Merge issues ✔: bulk bar ✘: not seen
Pre-built triage views Not checked ✔: sidebar views out of the box

Verdict: Mixed. Sentry suits a team sharing one backlog, with priority and merge built in. BugSnag's sidebar views and breadcrumb search make solo triage faster.

Real user monitoring and session replay

Replay lets you watch the clicks that led up to a failure, while real user monitoring times how quickly pages load for visitors. Both depend on a browser SDK, and I only ran Sentry's.

Sentry: Replays with an AI summary and the network log

Sentry's browser SDK recorded every session with replay at the default masking. Each replay opens on an AI summary:

Sentry session replay with an AI summary of the session

The summary gives one paragraph and a four-step timeline, with the wishlist crash in red at 00:04. Page text is masked with asterisks out of the box, and counters at the top track dead clicks, rage clicks and the 3 errors.

The broken cover image finally turned up in the replay's Network tab:

Sentry replay network tab listing every request

Every request has its method, status, size and duration, and the cover image appears as an img request with a 404. No issue was raised for it anywhere else.

Replays also attach to server errors. Because the storefront sent its replay ID along in the baggage header, the server's coupon error came with alice's session attached:

Sentry backend error with the browser session replay attached

Look for the request body, {"bookId":6,"coupon":"FREEBOOKS","quantity":1}, above the embedded player. You can watch the click that sent the bad coupon without leaving the server error.

Sentry also builds a Web Vitals dashboard:

Sentry web vitals dashboard with a performance score

It scored the storefront 90, with a P75 LCP of 92 ms, INP of 8 ms, CLS of 0.0007 and TTFB of 2.51 s. The dashboard opened with a "Save for Everyone" bar, which I left alone.

The page breakdown is less helpful for a hash-routed app:

Sentry web vitals grouped as Pageload and Navigation

Every route in the storefront is named /, so the list splits into "Pageload" and "Navigation" with no per-page rows. The deliberately slow book 3 page can't be picked out until you set custom transaction names.

BugSnag: Not tested

I didn't run BugSnag's browser SDK, so I can't report how it captures storefront errors or measures page loads. BugSnag's plans don't list session replay, according to its pricing page.

Real user monitoring comparison

Capability Sentry BugSnag
Session replay ✔: every session, text masked ✘: not listed on its plans
AI summary of a replay ✔: paragraph and timeline Not applicable
Network log in the replay ✔: caught the broken image Not applicable
Replay on a backend error ✔: through the baggage header Not applicable
Web vitals ✔: score and P75 values Not tested
Per-route vitals on a hash-routed app ✘: every route named / Not tested

Verdict: Sentry. It recorded replays, summarized them and tied them to server errors. BugSnag's browser monitoring wasn't tested, so this verdict covers replay only.

Neither tool could tell me which storefront page was slow. Sentry's vitals lumped every hash route under /, and BugSnag's plans don't include replay at all. In Better Stack, a single session from this storefront carried 30 frontend spans and 7 backend spans on one shared timeline.

Better Stack session timeline mixing browser spans and server spans

The backend service shows as "unknown" because the SDK set no service name, but the server spans sit right under the clicks that caused them.

I then asked RUM Insights which route loads slowest and why. It named /#/orders, with an LCP p75 of 1948 ms, ahead of /#/books/3:

Better Stack AI SRE ranking routes by LCP

Notice that it ranked hash routes individually, which Sentry's dashboard couldn't do here. It then traced the delay to the server:

Better Stack AI SRE tracing slow page loads to a blocked event loop

It blamed TTFB on an event loop starved by /search, counted every one of its 191 requests above one second, and ruled out the database. It wasn't perfect. It described the price lookups as slow code when they actually wait on an upstream, the chat cost $0.62, and the tag ignores headless browsers until you set collectBots.

Replay sessions next to their backend spans

Release tracking and regressions

Release tracking answers two questions. Did this deploy introduce the error, and did a bug you closed come back?

Both tools created releases from the version set in the SDK, with no deploy call. This is where the meaning of "fixed" starts to matter.

BugSnag: Fixed means fixed until a newer version

"Mark as fixed" opens a short dialog with an optional Markdown comment. The activity log then records the error as fixed "Until this error occurs again in a new version".

That rule is tied to the app version. More events on the same version won't reopen the error, which keeps late traffic from an old build out of your queue.

A project setting, "Mark errors as fixed after each release", can close everything on every release. It's disabled by default, so nothing changes status unless you act.

Sentry: You decide what resolved means

Sentry's resolve menu gives you a choice:

Sentry Resolved In menu with release and commit options

You can tie the fix to the next release, to the current semver release, to some other release, or to a commit, and each sets a different bar. Plain "Resolve", the button itself, sets no bar at all.

I learned that the hard way. A coupon error I'd resolved with the plain button came back within the same release:

Sentry issue regressed within release 1.0.0

The activity reads "Regressed in 1.0.0" under "Resolved · 18hr ago". If you want BugSnag's behavior, pick "The next release", after which the banner reads "resolved starting with a release after 1.0.0".

What happened when 1.1.0 shipped the same bug

I resolved the coupon error, shipped 1.1.0 without fixing it and replayed the traffic. Both tools reopened that error and left the other five alone.

Sentry: Regressed in the list, on the issue and in the release

Sentry marked the reopen in the issue list itself:

Sentry issues list with Regressed under the coupon error

"Regressed" sits under the coupon error's trend graph, while the others say "New" or nothing. You'd see it on a quick scroll.

The issue page repeats it:

Sentry coupon issue regressed in 1.1.0

The header reads "Unhandled | Regressed | POST /checkout", the button is back to "Resolve", and Activity says "Regressed in 1.1.0".

The wording slipped once. On another reopen, the activity entry compared 1.1.0 with itself "based on SemVer":

Sentry activity feed with the regression message

The second version number should be 1.0.0. The note below it, "A replay isn't available for this event", is expected, because the latest event came from an API user with no browser.

The release page gives regressions their own tab:

Sentry release 1.1.0 Regressed tab and failing transactions

"Regressed 1" lists only the coupon error, and the failing transactions table below puts POST /checkout on top with 30 failures.

The release tag split shows how the issue's events spread:

Sentry release tag split on the coupon issue

21 events, or 70%, came from 1.0.0, and 9, or 30%, from 1.1.0.

BugSnag: The reopen lives in one error's activity

BugSnag's inbox after 1.1.0 looked like this:

BugSnag inbox after release 1.1.0

The coupon error has no reopened or regressed badge, and the sidebar reads Open (6) and Fixed (0). You'd only notice the reopen if you opened the error or watched its count climb.

Inside the error, the activity feed tells the full story:

BugSnag activity showing the coupon error reopened in 1.1.0

The newest entry says BugSnag reopened the error because it "occurred in 1.1.0". Below it, my earlier fix is logged with its condition, "Until this error occurs again in a new version". The cause and the rule that triggered it are both on record.

The error's release summary adds the split:

BugSnag coupon error with its release breakdown

It shows 27 all-time events across Releases (2), with 51.9% on 1.1.0, and the button has gone back to "Mark as fixed".

Release stability in both tools

Both tools tracked sessions per release with no extra code. Sentry's release list showed crash-free rates:

Sentry releases list with crash-free rates for both versions

The first release reads a 90.364% crash-free rate, 90 crashes and 6 new issues. The second reads 90%, with 31 crashes and a new-issue count of zero, which is right, since 1.1.0 brought no new bug.

The 1.1.0 overview compares the release with the rest:

Sentry release 1.1.0 overview with the crash-free chart

The chart reads 90% with a "Release Created" marker, the failure rate is 18.45%, and Commits shows 0 because no commits were linked yet.

BugSnag's release list shows session stability instead:

BugSnag releases list with session stability for both versions

1.0.0 reads 83.103% across 290 sessions and 1.1.0 reads 83.893% across 298, both flagged "Critical stability" against the default 90% threshold. "Compare release performance" is greyed out without performance data.

The 1.1.0 release page lists what it saw:

BugSnag release 1.1.0 page with errors seen

It shows 50.68% adoption, a "Configure source control links" prompt and, under "Errors seen", the coupon error with 14 events on this release.

Its "Errors introduced" tab was empty:

BugSnag release 1.1.0 with no errors introduced

"No errors matching your filters" is the correct answer here. There's no tab for errors that came back, which is where Sentry's Regressed tab earns its place.

The two stability figures count sessions differently, so don't compare 90% with 83%. What matters is that each tool gave you a per-release number for free.

Sentry on a bad deploy

I only ran 1.2.0 through Sentry. After sentry-cli releases set-commits --auto linked the repository, the new payment error showed a suspect commit:

Sentry payment error with a suspect commit and breadcrumbs

The frame at server.js:173 shows the paymentAttempts % 5 check, and the breadcrumbs run from "slow query: SELECT book for checkout" to "payment gateway slow to respond, retrying". My test repository has a single commit, so the suspect commit could only ever name that one.

Release tracking comparison

Capability Sentry BugSnag
Releases from the SDK version ✔: no deploy call ✔: no deploy call
Resolve options ✔: now, next release, a release or a commit ✔: fixed until a new version
Plain resolve on more events in the same release Reopens Stays fixed
Only the resolved error reopened on 1.1.0 ✔: yes ✔: yes
Regression label in the list ✔: Regressed ✘: none
Regression on the release page ✔: Regressed tab ✘: errors seen and introduced only
Reopen in the activity feed ✔: with a version wording slip ✔: with the rule that fired
Stability per release ✔: crash-free sessions ✔: session stability
Suspect commits ✔: after set-commits Not tested

Verdict: Sentry. Both reopened only the bug I'd resolved, but Sentry put the regression where you'd see it, in the list and on the release. BugSnag's version-tied "fixed" is the safer default, and Sentry only matches it if you remember to choose "The next release".

BugSnag kept the reopened coupon error out of sight in its inbox, and Sentry flagged it but then spawned two duplicate groups once 1.2.0 moved the stack. I ran the same releases through Better Stack. After 1.1.0, the coupon error's row changed to a red "Reoccurred" in the error list itself.

Better Stack error list where only the coupon row reads Reoccurred

Only that row changed, so the regression is visible without opening anything. The error page carries the same history in order:

Better Stack coupon error activity with the reoccurrence

"Error reoccurred" sits above the resolve and the first appearance, with no version mix-up. Then the bad deploy landed, and the groups held:

Better Stack payment error with its source code

The payment error stayed one group with 10 exceptions across different amounts, and the coupon error stayed one group across all three releases. Better Stack has no separate Regressed tab on the release page, and its toast said "resolved in this release" after I chose "Resolve in next release", so it isn't flawless.

Track regressions where you triage errors

Performance monitoring

Not every bad deploy throws an exception. Some just make requests slower, and an error tracker can only help if it can see time.

Sentry: Traces from the same SDK

Sentry traced every request through the SDK already sending errors. Grouping the spans by endpoint gave me p95 durations straight away:

Sentry trace explorer with p95 duration per endpoint

GET /prices/:id led at 3.58 s and GET /search followed at 1.95 s, while checkout and book lookups stayed under 5 ms. Both slow paths I'd seeded sat at the top.

Opening one /search trace showed where the time went:

Sentry trace waterfall for a slow search request

The request took 1.99 s, and its database span took 0.23 ms. The time is in the handler's own code, so you'd stop looking at the query.

The price lookup told a different story:

Sentry trace with a slow outbound call returning 503

The outbound http.client span took 3.54 s with the price service's spans nested under it. A side panel flags the 503 and notes that no issue is attached to the span. Sentry raised no performance issue for either slow path.

Release 1.2.0 made checkout slow, and the waterfall put the cause in plain view:

Sentry trace waterfall for a slow checkout on release 1.2.0

Inside a 2.26 s checkout, SELECT book for checkout takes 1.79 s and the new "charge card" span takes 459 ms and fails. The trace starts at the shopper's click in the browser.

Grouping checkout's p95 by release shows when it began:

Sentry checkout p95 grouped by release

1.0.0 sat at 5.29 ms and 1.1.0 at 3.63 ms, then 1.2.0 jumped to 5.93 s. The line breaks upward exactly where the bad deploy starts.

Sentry: Profiling found the hot line, after a detour

The /search profile, captured by @sentry/profiling-node, singled out one function:

Sentry profile with the hottest frame in the search handler

The tooltip reads "1.91s (96.23%)" at server.js:98:20, marked as an application frame. That's the CPU-heavy match I seeded.

The sales report job profiled cleanly, too:

Sentry profile of the sales report job

buildReport took 882 ms, 98.7% of the run, under a stack that starts at processTimers.

Getting to those profiles took a detour. The transaction summary's Profiles tab was empty:

Sentry transaction Profiles tab with no data

"This flamegraph has no data" and "Profiles (0)" appear even though continuous profiles existed. I reached them through the trace instead.

The profiles overview missed the search handler as well:

Sentry slowest functions list in the profiles explorer

"Slowest Functions" lists buildReport, withSpan and log, but never the anonymous /search handler. The slowdown in 1.2.0 comes from waiting, so I didn't profile it.

BugSnag: Performance waits for OpenTelemetry

BugSnag's Performance tab has Page Loads, Inbound Requests, Outbound Requests and Custom Spans:

BugSnag performance tab asking for the OpenTelemetry SDK

All four were empty, and the page asked me to install the OpenTelemetry SDK to turn performance on. BugSnag accepts that data, but adding it is a separate instrumentation project that I didn't take on, so its performance features are untested here.

Profiling sits behind the same OpenTelemetry requirement.

Performance comparison

Capability Sentry BugSnag
Server traces out of the box ✔: same SDK as errors ✘: needs OpenTelemetry
p95 per endpoint ✔: slow paths on top Not tested
Outbound HTTP calls ✔: 503 span visible Not tested
Browser to server trace ✔: one waterfall Not tested
The 1.2.0 database slowdown ✔: a 1.79 s span Not tested
Latency by release ✔: p95 grouped by release Not tested
Profiling ✔: hot line found through the trace ✘: needs OpenTelemetry
Automatic performance issues ✘: none raised Not tested

Verdict: Sentry. It measured both slow paths and the bad deploy with nothing beyond its own SDK. BugSnag can take OpenTelemetry data, and you should test that route yourself before ruling it out.

BugSnag's Express SDK gave me no spans and has no log store, so seeing the 1.2.0 slowdown there means adding OpenTelemetry and a second product. Sentry showed the waterfall, but you pay for that by adopting its whole platform. I pointed the same Sentry SDK at Better Stack, changed nothing in the code, and opened the failing checkout from its error.

Better Stack spans on a failing checkout with the slow SELECT

The request ran 2.19 s. Of that, 1.53 s went to SELECT book for checkout and 660 ms to the "charge card" span. That's the same answer Sentry gave, reached in one click from the error.

The "View related" menu on any exception is where the jump happens:

Better Stack View related menu on an exception

Logs, spans, the release, session replays and an AI SRE investigation all sit in one list. "View logs" opens Live tail filtered to the exception's trace ID:

Better Stack Live tail filtered to the failing request

The slow-query warning and ERROR POST /checkout failed sit together for that one request. The Service column stays empty because the Sentry SDK sets no service name, which you'd fix in config.

Jump from an error to its logs and spans

Logs and metrics

Logs explain the steps an error skipped, and metrics turn app events into numbers you can chart. Only one of these two tools stores either.

Sentry: Logs and business metrics beside the errors

Sentry's Logs explorer held the app's structured logs:

Sentry logs explorer with a per-minute chart

It counted 129 logs in the hour, with severity as a colored dot and the sales report job logging once a minute.

Grouping by message gives you a count check that Dedupe can't touch:

Sentry logs grouped by message

"order placed" appeared 61 times and "POST /checkout failed" 12 times. That 12 is how I knew the coupon error's 9 events were short.

Release 1.1.0 told the same story:

Sentry logs grouped by message for release 1.1.0

The filter release is monitoring-lab@1.1.0 shows "POST /checkout failed" 11 times, against 9 coupon events in the same release.

Number filters take an unusual syntax:

Sentry log search with attribute filters

"total > 50" only worked when I typed tags[total,number]:>50, after which it returned "7 matches of 103 logs".

Inside a trace, the Logs tab merges both sides of the app:

Sentry trace logs from the browser and server

The browser's "checkout partly failed" sits next to the server's "POST /checkout failed", each with its error attached.

Metrics handled business numbers, too:

Sentry checkout revenue grouped by coupon

I summed checkout.revenue and split it by coupon. Orders without a coupon brought in 2,652.89, SAVE10 orders 442.79 and HALFOFF orders 118.99, across 61 data points.

BugSnag: No logs or metrics product

BugSnag has no log store and no custom metrics. Breadcrumbs and metadata travel with each error, but anything else your app writes needs another tool.

Logs and metrics comparison

Capability Sentry BugSnag
Log storage ✔: Logs explorer ✘: not offered
Logs linked to a trace ✔: browser and server together ✘: not offered
Count check against errors ✔: logs aren't deduplicated ✘: no logs to compare
Number filters on attributes ✔: needs the tags number syntax ✘: not offered
Custom metrics ✔: sums, percentiles and group by ✘: not offered

Verdict: Sentry. Its logs and metrics sit next to the errors, and the log counts exposed the events its SDK dropped. With BugSnag, plan on a separate logging tool.

Uptime, alerts and integrations

Getting told about a problem matters as much as seeing it. I tested one alert in Sentry and looked at what each tool connects to.

Sentry: Monitors for metrics, crons and uptime

Sentry's monitor picker covers more than errors:

Sentry monitor types including cron and uptime

"Metric", "Mobile Build", "Cron" and "Uptime" sit beside the issue alert option. I didn't test the uptime or cron monitors.

I built one issue alert for the price service failures:

Sentry issue alert rule for upstream errors

The builder splits triggers, filters and throttling into separate blocks, so you can say "six of these in five minutes" without code.

It fired during the test:

Sentry alert history with two triggers

"Total Triggers 2" lists the UpstreamError and the time it fired. Sentry's integrations page listed Slack, Discord, Microsoft Teams, Jira, Linear, GitHub, GitLab, Vercel and Cursor, none of which I connected.

BugSnag: Integrations grouped by job

BugSnag's settings sort integrations by what they're for. Team notifications cover Slack and Datadog, issue trackers cover Jira and Trello, incident management covers PagerDuty, and data forwarding covers webhooks and Splunk.

Each error also has a "Create or link an issue" panel, and the SmartBear MCP Server appears in the same list. I didn't set up or test a BugSnag alert.

Alerts comparison

Capability Sentry BugSnag
Error alerts ✔: fired twice in my test Not tested
Metric alerts ✔: available, not tested Not tested
Cron monitoring ✔: available, not tested Not observed
Uptime monitoring ✔: available, not tested ✘: needs another product
Chat integrations ✔: Slack, Discord, Teams ✔: Slack
Issue trackers ✔: Jira, Linear, GitHub, GitLab ✔: Jira, Trello
Incident tools ✔: PagerDuty and Opsgenie ✔: PagerDuty

Verdict: Sentry on availability. It offers uptime and cron checks in the same product, and its error alert worked. I didn't test BugSnag's alerts, so this says nothing about how well they deliver.

AI-assisted debugging

Both tools tie their AI to something you connect first. I ran Sentry's Seer with my repository connected, and I didn't run BugSnag's "Fix with MCP", so this section isn't a head-to-head.

Sentry Seer: Right about the bug, wrong about the slowdown

Before I linked GitHub, Seer wouldn't start:

Sentry Seer requirements asking for a connected repository

The panel asks for a GitHub or GitLab repository and links to "Manage repositories". Without one, there's no Seer.

With the repository connected, "Start Analysis" on the coupon error returned a root cause in about 15 seconds:

Sentry Seer root cause for the coupon TypeError

It found that the handler reads .discount from an unvalidated coupon lookup, that COUPONS only holds SAVE10 and HALFOFF, and that FREEBOOKS returns undefined. It cited the event and the exact file ranges it read from the repository, and it assigned the issue to me "due to Seer Suggestion".

The plan that followed was sensible:

Sentry Seer plan for fixing the coupon error

It proposed a 400 response for unknown coupons, optional chaining on the failing line and removal of the bug comment. I stopped short of "Yes, write a code fix", since that path can draft a pull request against the repository.

That analysis stayed with the error when it came back in 1.1.0:

Sentry regressed issue with the Seer root cause in the sidebar

The sidebar still holds the earlier root cause and plan, with "Open Autofix", so whoever picks up the regression starts with an answer.

On 1.2.0, Seer explained the new payment error in about 20 seconds:

Sentry Seer root cause for the payment error

Seer spotted the paymentAttempts counter at module level and the BAD_DEPLOY switch keyed to 1.2.0. Its steps to reproduce the failure were correct. It said nothing about the slow queries, because it only looks at the one error.

For the wider question, I opened the Seer Agent chat, which carries a beta badge, and asked what changed between 1.1.0 and 1.2.0:

Sentry Seer Agent answer comparing releases

In 51.1 seconds it counted 3 new issue groups, which includes the two duplicates, and charted checkout p50 rising from 1.7 ms to 3.77 s. No cost was shown.

The explanation further down missed:

Sentry Seer Agent pinning the checkout slowdown on payment retries

It said the slowdown was "driven by the upstream timeout on failed payment attempts". The trace it had access to showed the SELECT at 1.79 s and "charge card" at 459 ms.

A follow-up about spans got the numbers right and the story wrong again:

Sentry Seer Agent span table for the slow checkout

Its table has SELECT book for checkout rising to 2,640 ms from 0.1 ms, yet Seer still said the queries slowed because of payment retries. The queries run before the payment call, so removing the payment code wouldn't have fixed them.

BugSnag: Fix with MCP hands the error to your own assistant

BugSnag puts a "Fix with MCP" button in the error toolbar. Clicking it opened this:

BugSnag dialog prompting for the SmartBear MCP install

The dialog notes that I haven't used the MCP server on this project yet, then offers to install SmartBear's MCP Server. I cancelled, so I can't say how well your coding assistant would do with BugSnag's data.

BugSnag doesn't run root-cause analysis inside its own interface. The design assumes you already have an assistant and want the error delivered to it.

AI comparison

Capability Sentry BugSnag
Where the AI runs ✔: inside Sentry Your own assistant over MCP
Needs before it works A connected repository The SmartBear MCP Server
Root cause on one error ✔: correct in about 15 seconds Not tested
Fix plan ✔: sensible, can draft a PR Not tested
Release-wide question ✔: right numbers, wrong cause Not tested
Price Add-on: price not listed Uses your own assistant

Verdict: Not compared. Seer was right on both errors and wrong about why checkout slowed, and it had my code to work with. I didn't run BugSnag's MCP route, so there's no basis for ranking one over the other.

Seer blamed the payment code for a database slowdown even after a follow-up, and BugSnag leaves the analysis to whatever assistant you bring. I gave Better Stack's AI SRE the same release question, without access to my repository.

Better Stack AI SRE answer on what the 1.2.0 deploy changed

It put the p50 of SELECT book for checkout at 2.6 s on 1.2.0, up from 0.13 ms, and noticed the other statements hadn't moved off roughly 0.1 ms. From that it cleared the database host and pinned the slowdown on the checkout code. That's the separation Seer never made.

The second half of the answer handled the payment error on its own terms:

Better Stack AI SRE root cause and recommendations for release 1.2.0

It found the new "charge card" span failing 10 of 48 times, all on 1.2.0, linked it to the new error and recommended a rollback. It took about 4 minutes against Seer's 51 seconds and cost $0.49, and without the code it described the deliberate failure as a timeout set too short.

Ask AI SRE what changed in your last release

Pricing

Sentry sells one platform with quotas per product, and BugSnag prices error events and spans on volume sliders. The figures below come from each vendor's pricing page between October 23 and 26, 2026, so confirm them before you buy.

Free plans and trials

Feature Sentry BugSnag
Permanent free plan ✔: Developer ✔: Free
Users 1 1
Errors a month 5,000 7,500 events
Spans 5M 1M, needs OpenTelemetry
Session replays 50 ✘: not listed
Logs 5 GB ✘: not offered
Retention Not covered in this snapshot 7 days
Trial 14-day Business trial, no card 14 days, no card

Sentry's onboarding also listed 5 GB of metrics on the free plan once the trial ends.

During the trial, Sentry's usage page showed how roomy the Business quotas are:

Sentry trial usage across errors, logs, spans and replays

My whole test used 194 of the 1M errors and 4K of the 100M spans, and each line was billed at $0.00. You'll have room to test everything during the trial.

BugSnag's trial ran two plans side by side:

BugSnag billing page with error monitoring and performance trials

"Error monitoring: Trial Plan" and "Performance: Trial Performance" are billed separately, as event usage and span usage.

Entry-level paid plans

Feature Sentry BugSnag
Entry paid plan Team Select
Entry plan, billed monthly $29 a month Price not listed: set on a volume slider
Entry plan, billed annually $26 a month Not listed
Next plan Business Preferred
Next plan, billed monthly $89 a month Price not listed: set on a volume slider
Next plan, billed annually $80 a month Not listed

BugSnag's slider runs Select from 50,000 to 3M events and 1M to 300M spans, with 60-day retention and unlimited users. The page shows "starting at $0" next to the slider, so you'll need to set your own volume to see a figure.

What costs extra

Need Sentry BugSnag
AI root-cause analysis Seer add-on: price not listed Your own assistant over MCP
Performance Spans from the same SDK Span volume, plus your OpenTelemetry setup
Logs Part of the platform ✘: needs another product
Session replay Part of the platform ✘: not listed
Uptime checks Part of the platform ✘: needs another product

Comparing the actual cost

For one developer on errors alone, BugSnag's free plan gives you 7,500 events a month to Sentry's 5,000. The catch is seven-day retention, which means last week's bug is gone by the time you get round to it.

For a team, Sentry is easier to budget. Team at $29 a month is a fixed number, while BugSnag's Select and Preferred depend on where you set the slider.

The bigger cost is what each plan leaves out. With BugSnag, you'd pay for logs and uptime somewhere else and build an OpenTelemetry rollout for performance. With Sentry, those come in the same bill, but Seer is an add-on with no published price.

If you're weighing BugSnag against a tool with no free tier at all, our BugSnag vs Airbrake breakdown runs the numbers.

Verdict: Sentry for a team, BugSnag for a solo start. Sentry publishes its prices and covers logs, replay and tracing in one plan. BugSnag's free plan is roomier on events, as long as seven days of history is enough.

Full feature comparison

This table combines everything I observed in both tools.

Feature Sentry BugSnag
Trial without a card ✔: 14-day Business trial ✔: 14 days
Browser and server in one project ✔: one DSN Not tested
Six seeded server bugs ✔: six issues ✔: six errors
Handled and unhandled marking ✔: Unhandled label ✔: badge on every row
Event counts against app logs ✘: Dedupe dropped repeats Not checkable inside BugSnag
Source lines on server frames ✔: inline ✘: frames only
Browser source maps ✔: with sentry-cli Not tested
Breadcrumb search ✘: timeline only ✔: search and type filter
Correlated events by user and session ✘: not observed ✔: own tab
Browser error linked to backend error ✔: shared trace Not tested
Grouping after a code change ✘: two duplicates on 1.2.0 Not tested
Grouping rules Merge Error class or context
Priority and merge ✔: both ✘: neither seen
Session replay ✔: with AI summary ✘: not listed
Web vitals ✔: hash routes all named / Not tested
Resolve options ✔: now, next release, a release or a commit ✔: fixed until a new version
Regression label in the list ✔: Regressed ✘: activity feed only
Regressed tab on the release ✔: yes ✘: not seen
Release stability ✔: crash-free sessions ✔: session stability
Suspect commits ✔: after set-commits Not tested
Server tracing ✔: same SDK ✘: needs OpenTelemetry
Profiling ✔: continuous profiles ✘: needs OpenTelemetry
Logs ✔: Logs explorer ✘: not offered
Custom metrics ✔: group by any attribute ✘: not offered
Error alerts ✔: fired twice Not tested
Uptime checks ✔: available, not tested ✘: needs another product
AI analysis ✔: Seer, needs a repository Fix with MCP, not tested
Permanent free plan ✔: 5,000 errors ✔: 7,500 events
Published paid prices ✔: Team and Business ✘: volume slider

Which should you choose?

The choice comes down to whether you want one tool for the whole investigation or a sharp error tool next to the ones you already run.

Choose Sentry if you want the investigation to keep going past the error

Sentry is the better pick when you need to get from a symptom to its cause without switching products. Inline source, a browser error linked to the backend error, a replay on the server issue, a trace waterfall and a profile took me from a failed click to the slow line inside one interface.

It also made regressions loud. The reopened coupon bug was labelled in the list, on the issue and on the release, and the logs explorer caught the events its SDK had quietly dropped.

The trade-offs are real. Plain "Resolve" reopens on the next event, so you'll want "The next release" as a habit. A code change created duplicate groups, Seer needs your repository and blamed the wrong cause for the slowdown, and the interface takes longer to learn.

Grouping is where our Sentry and Airbrake head-to-head puts Sentry next to a tool that merged these two TypeErrors.

Choose BugSnag if errors and release stability are the whole job

BugSnag suits a team that already has a place for logs and performance and wants a calm, focused error inbox. Its badges, sidebar views, searchable breadcrumbs and correlated events made each error quick to read.

Its definition of "fixed" is the most sensible default in this comparison. An error stays closed until it shows up in a newer version, so late traffic from an old build can't drag it back.

You'll give up source lines on server frames, and a regression won't stand out in the inbox. Performance needs an OpenTelemetry rollout, there are no logs, and the free plan keeps seven days of data.

For a look at how BugSnag fares against a tool with replay but no tracing, read our comparison of BugSnag and Rollbar.

Final thoughts

Both tools caught everything, so the real decision is how much you want your error tracker to do once the error is in. Sentry will chase the cause through traces, logs, replays and profiles, and it will also reopen a bug the moment you forget to pick a release. BugSnag keeps its promises small and keeps them well, then sends you elsewhere for the slow query.

If your team already runs good logging and tracing, BugSnag's narrower product is less to learn and harder to misuse. If it doesn't, you'll end up buying those pieces anyway, and Sentry has them in the same bill.

The coupon bug came back in both tools, and only one of them told me without being asked.