Unreal Ops Platform
Unreal Ops Monitor
Crashes, uptime, and the job that was supposed to run.
An unhandled exception in a shipped app is usually invisible to you. The user force quits, maybe reinstalls, and never files a report. Monitor is the piece of your stack whose only job is to notice, and then to hand you a stack trace you can actually read. It watches the other kind of failure too, the kind that happens while none of your code is running: a site that stopped answering, a certificate nobody renewed, a domain about to lapse, a scheduled job that quietly stopped firing. It is built to be cross platform. Flutter is the first implementation finished and verified end to end, and the platform table below says exactly where every other one stands.
Monitor runs at monitor.unrealops.ai and takes real crashes from Flutter and Next.js apps today. This site is one of the Next.js apps it watches, and a deliberate crash thrown from this site's own deployed, minified bundle came back through Monitor's API resolved to the exact file and line in this repository, which was the bar this page set for calling a platform supported. You can create an account on the free plan and the next screen has your DSN on it. Billing is the piece that does not exist, so the prices further down are published rather than charged: there is no checkout, no trial, and every account is on the free plan whichever tier it picked.
What it does
Every event arrives with the stack trace, the breadcrumbs that led up to it, the device and OS, the locale, the app version, and the release it belongs to. Nothing useful is left behind on the user's device.
Identical faults collapse into a single issue with a count, a first seen, a last seen, and the list of releases affected. A thousand crashes read as one problem to fix rather than a thousand rows to scroll past.
Stack traces you can read
Release builds obfuscate, and a raw trace from a production build is a wall of hex that tells you nothing. Monitor takes the debug symbols your build produces, uploaded at build time, and gives the trace back in the shape you wrote it: your file names, your line numbers, your function names. The symbol table is extracted once and the uploaded artifact is thrown away.
Every frame is labelled with what happened to it. A frame that could not be resolved says so, and says which symbol file was missing, rather than quietly showing you an address and letting you assume it was the best anyone could do.
The failures that happen while nothing is running
A crash report needs your code to be running to exist. A good share of what actually takes a small product off the air does not: the site stops answering, a certificate lapses on a Sunday, a domain nobody remembered to renew expires, the nightly backup quietly stops firing. Monitor watches all four, and none of them needs an SDK in anything.
An uptime check runs every five minutes, and that number is the schedule the platform actually keeps rather than one chosen to sound attentive. A check is called down after three consecutive failures, because one failed request is a dropped packet or a container being replaced, so an outage is noticed roughly ten to fifteen minutes after it starts. That sentence is on the screen where you set the check up rather than in a footnote, and it is the honest description of what a five minute cron can promise. Five checks per project, which is a division of what this deployment can afford rather than a tier.
The certificate expiry is read off the same TLS handshake the check already made, so it costs nothing extra and cannot disagree with the check beside it. The domain expiry is a different thing entirely, an RDAP query to the registry, so it is asked once a day at most and a registry that will not answer is reported as not answered rather than guessed at.
A scheduled job reports for itself: a bare curl on the end of a crontab line, with nothing to install and nothing to sign, because a shell script cannot be asked to construct a signed request. Ping once at the start and again at the end and Monitor can tell a job that started and never finished from one that never started, which are different problems with different causes. Late but still inside its grace period is a state on the screen, not an email, because an hourly job that runs ninety seconds late every hour is not news.
A status page, for the people asking whether it is you
The checks above can drive a status page, public at a slug you choose or private to your own organization. A component whose check fails opens an incident on it without anybody typing, and a component nothing has ever checked says so rather than being rounded up to operational.
Incidents take updates, maintenance windows are scheduled ahead and suppress what they cover, and people can subscribe by email with a confirmation step. A public page carries no identifier of any kind from inside the platform, not the organization, not the project, not the check, because a field that does not exist cannot be leaked by a template that forgets. It reads and never writes, and when it cannot be rebuilt it serves the last answer that worked and says how old that answer is, because a status page that returns an error turns we are having trouble into we have gone away.
Run it next to Sentry before you trust it
Nobody should move their crash reporting to a service they have not watched work. So Monitor will forward a copy of everything it accepts to a Sentry DSN you give it. Point your app at Monitor, paste your existing Sentry DSN into the upstream field, and both backends receive the same traffic from the same builds.
Compare for as long as you like, on your own crashes rather than on a demo. Clearing the upstream field stops the forwarding on the next event, and it does not need a rebuild or a redeploy to stop. If Monitor turns out to be wrong for you, Sentry never stopped working and you change one string to go back.
Session replay and profiling do not ship
Both were assessed properly and neither was built. That belongs on this page rather than in a changelog, because it is the thing you would otherwise find out after moving. An SDK configured to send either one is answered so it stops retrying, the items are counted where you can see what your app is sending that will never be shown to you, and nothing is stored.
The arithmetic is the easy half of the argument. One ten minute session replay costs about what 390 stored events cost, and roughly 1,500 of those sessions would fill Monitor's entire storage slice, leaving nothing at all for crashes, sessions or symbols. A tenth of the slice divided between the organizations these budgets are cut for would buy about nineteen recorded sessions a month each, which is not an allowance worth selling.
The deciding argument is not the money. A stack trace is a description of a program. A replay is a recording of a person's screen, and that person is your user, who has no relationship with us at all. Storing them makes personal data the ordinary content of a row rather than an occasional accident inside an exception message, and that is a real obligation behind every deletion and retention promise. It is answerable, and it is not answerable by one person running this alongside client work.
Profiling is a different no. Its volume is affordable; its capture path is not dependable. It needs a policy header set on your own responses, a profiler that exists in one browser family, and a transaction to attach to, and it switches itself off for the whole page on the first failure. There is no browser in this test suite, so nobody here can prove it works, and a capability nobody can prove is not one to sell.
What exists instead is the mirror above. Point your app at Monitor, keep your Sentry DSN in the upstream field, and replay carries on being recorded in Sentry while everything else lands here. For the cheaper half of what replay is used for, which is what the user was doing before it broke, breadcrumbs are already stored on every event.
Caps that stop instead of billing you
A crash loop in one app produces events as fast as the device can restart. Everywhere else, that is an unbounded bill arriving on a Tuesday, which is the failure mode that teaches people to turn monitoring off. Monitor answers a runaway with a refusal.
Two ceilings sit in front of ingest, checked before an envelope is parsed or stored. Over either one, ingest refuses in the way the SDK already understands, the client stops sending, and the drop is counted and shown to you. There is no overage line on any plan because there is no overage.
Which platforms work today
- FlutterAvailable
Verified end to end, by doing it rather than by reading code: real envelopes grouped at the live endpoint, symbols uploaded at build time and traces returned readable, release health computed per release, and an alert email actually delivered.
- Next.jsAvailable
Verified end to end on this site, on both halves of the build. A deliberate browser crash from the deployed bundle and a deliberate server crash from a route handler each came back through Monitor's API naming a real file and line in this repository: the server one arrived as E (/var/task/.next/server/chunks/[root-of-the-server]__1a46q5s._.js:1) and read back as src/app/api/monitor-check/route.ts line 25, which is the line that throws. Server maps are a per project setting and they are off by default, because they spend your own pooled symbol allowance rather than ours: measured on this site the server half stores 2.3 MB a release against the browser half's 0.8 MB, and uploads are addressed by content, so a redeploy pays only for the chunks that actually changed. A frame we still cannot resolve says which file's map is missing rather than pretending. What remains genuinely impossible on Vercel is the other approach, letting the running function resolve its own stack: we checked inside a live function and the maps are not shipped into it. Resolving an uploaded map at ingest never needed them there, which is the half we built.
- React NativeComing Soon
Planned, with no code written. It is deliberately not a blocker for anything above it.
- ExpoComing Soon
Planned alongside React Native, with no code written.
This table is the whole list. A Sentry SDK for some other platform can send an envelope this ingest would accept, and that is not the same thing as support: native iOS, native Android, Node and everything else are missing from this table on purpose, and will stay missing until a real project proves them. Two things below sit outside the table on purpose: an uptime check and a heartbeat watch a url rather than an app, so they work against anything that answers a request or can run curl, whatever it was written in.
What Monitor does
Everything here runs today. Where a capability needs an SDK in your app it works on the platforms marked Available above; where it only needs a url, it does not care what you built the thing in. Where something is not built, or is built and not yet proved on one of the two platforms, the entry says so in its own words rather than leaving it for you to discover.
Readable stack traces
Symbol upload at build time, so a production trace comes back with your file names and line numbers instead of obfuscated hex. Included on every tier, free one included.
Issue grouping
Identical faults collapse into one issue with a count, first seen, last seen, and the releases affected. The grouping rule and its inputs are shown, so a surprising group can be explained rather than argued with.
Release health
Crash free sessions and crash free users per release, compared against the release it replaced, so a bad build is obvious to you before it is obvious in the reviews.
Alerts to email, Slack and signed webhooks
A new issue, a regression, a site that went down or a job that did not run sends one notification, through one decision the three channels share. Per issue cooldowns and hourly and daily ceilings mean a crash loop costs one message rather than four hundred, on every channel at once. A webhook is signed over the timestamp and the body together, so a captured delivery cannot be replayed at you next week, and rotating the secret keeps the old one valid for a day so rotation is not an outage.
Uptime, with the certificate and the domain
A check every five minutes, called down after three consecutive failures, so an outage is noticed ten to fifteen minutes in and the screen says exactly that instead of implying a continuous watch. The certificate's expiry is read off the same handshake, so it costs nothing extra. The domain's expiry comes from the registry over RDAP, asked at most once a day, and a registry that will not answer is reported as unanswered rather than guessed.
Cron and heartbeat monitoring
A bare curl on the end of a crontab line, with no SDK and nothing to sign. Ping at the start and at the end and Monitor separates a job that started and never finished from one that never started. Grace periods mean late is a state on the screen rather than an email, and the last twenty runs are kept so you can see whether last night was unusual.
Status pages, public or private
Components driven by the checks above, incidents opened automatically when one goes down, maintenance windows that suppress what they cover, and email subscribers who confirm first. A public page carries no identifier from inside the platform, and when it cannot be rebuilt it serves the last good answer with its age on it rather than an error.
Performance traces and structured logs
Transactions with the span tree underneath them, and log lines searchable beside the release and trace they belong to. Both are off in every Sentry SDK until you turn them on, and both spend the same pooled allowance crashes do: a transaction costs one event, ten log lines cost one event, and the two together may take at most two fifths of a month, so a month of tracing can never leave you with no crash reports. Log lines are scrubbed before anything is written, so a token pasted into a log line is not stored anywhere to leak later. Both were built against the JavaScript SDK's own wire shapes and are proved on Next.js; the same ingest accepts them from the Flutter SDK and nothing in that path is platform specific, but nobody here has driven it end to end, so treat Flutter as unproved rather than promised.
Breadcrumbs and context
The navigation, network calls, and log lines that preceded the fault, timed as an offset from the crash, plus device, OS, locale, and app version on every event.
Saved views and a health screen
A filter you keep going back to, saved as a screen and a query rather than as a copy of the data, so it cannot go stale or disagree with the screen it opens. The health screen composes what the other screens already know and answers the one question none of them does: whether anything here needs attention, including whether the alerts have anywhere to go.
Ceilings you can see
A per minute ceiling catches a crash loop within the minute, a monthly ceiling catches the slow bleed, and every refusal is counted against a reason on the usage screen rather than being silently lost.
Who it is for
- Solo developers and small teams shipping apps to the app stores.
- Agencies and contractors maintaining apps they built for somebody else.
- Anyone who currently finds out about a crash from a one star review.
- Anyone whose last outage was reported to them by a customer.
- Anyone running a backup or an import on a schedule that would fail silently.
- Anyone who has turned monitoring off because the bill stopped being predictable.
Built on open source
Monitor uses the open source Sentry SDKs, unmodified, pointed at ingestion we run ourselves. That is a deliberate choice. Those SDKs are mature, they are maintained by people who do nothing else, and they are not ours to quietly break. Nothing from the commercial Sentry backend is involved.
The practical consequence for a platform in the table above: adopting Monitor is a change to one DSN string. No rewrite, no shim, no second package fighting the first one for the error handler. The consequence for a platform not in that table is the opposite, and worth stating plainly: an SDK that can send us an envelope is not a platform we support, and we will not list one as supported on that basis.
What it will cost
Published before there is any way to pay them, because a price argued with early is cheaper to change than one defended after launch. The free plan is open and real. The paid ones are prices rather than purchases: there is no checkout on this page or on Monitor's own, and card payments are not switched on.
Developer
Free
Enough of the real product to judge it, including the part that makes it worth having.
- 1 project
- 5,000 pooled events per month
- 7 day retention
- Symbolication included
- 5 MB of symbols, about one release
- Email alerts
- 1 user
Open at monitor.unrealops.ai. One form, and the next screen has your DSN on it.
Solo
$13per month
One person or one small team shipping a handful of things.
- 3 projects
- 50,000 pooled events per month
- 30 day retention
- Unlimited teammates
- Release health
- Symbolication
- 15 MB of symbols, about three releases
- Standard alerts
Not purchasable. Billing is not built.
Studio
$39per month
A studio or agency carrying other people's apps as well as its own.
- 10 projects
- 250,000 pooled events per month
- 90 day retention
- 50 MB of symbols, about ten releases
- Slack and webhooks
- Advanced alerts
- Priority support
Not purchasable. Billing is not built.
Agency
About $79per month, later
The tier above Studio, for when ten projects stops being enough. It comes after launch.
- More projects and a larger pooled quota
- Shape still open, which is why the price is approximate
Not a tier you can pick. It is what comes next, not what exists.
The plan stops. It does not bill you.
This is the difference that matters. At your monthly limit, ingest refuses further events in the way the SDK understands, the client stops sending, and the refusals are counted and shown to you. Nothing keeps accepting events and settles up later, so there is no overage rate to look up and no invoice you did not expect. If you would rather be billed than capped, Monitor is the wrong product.
Quotas are pooled across your organization
The event allowance on every tier is organization wide, not per project. Five thousand events on the free tier is five thousand across everything you run. A quiet project does not waste an allocation it never used, and a noisy one does not need its own.
Symbolication is on the free tier on purpose
Readable traces are the product, not the upsell. Putting them behind the first paid tier would mean a free account never sees what Monitor actually does, so symbolication is included at Developer and stays there.
Symbol storage keeps your newest releases
Readable traces need a build's debug files, and those are the one thing on this page that does not reset with the month, so every tier now states how many it holds. When the allowance is full, uploading a new release deletes the oldest release's symbols to make room. The build you just shipped always resolves, and an older one stops. An upload is only refused if a single release is larger than the whole allowance, and then the message says what that release weighed and what your tier holds. A smaller tier keeps fewer releases of history, not less of the product.
Traces and logs come out of the same allowance
There is no separate line for them and there is not going to be one, because what this platform is actually short of is one thing and a second allowance would be a second number to keep in step with the first. A transaction costs one event. Ten log lines cost one event, which is the ratio of what the two cost to store rather than a round number somebody picked. Between them they may take at most two fifths of a month, so turning tracing on cannot leave you at the end of the month with no crash reports, and the ceiling is released day by day rather than all on the first, so a client sampling everything cannot spend the month in an afternoon.
Annual is about two months free
Paid tiers billed yearly work out to roughly ten months of the monthly price for twelve months of service. That is the intent rather than a button, since there is no billing yet.
Nothing on this page can be bought. Billing is the last unbuilt piece: the free plan is open and works, and paying for a bigger one is what is still missing, so every account is on the free plan whichever tier it picked. These prices are published early so you can tell us they are wrong while changing them is still free.
The rest of the platform
Monitor shares its account and its project structure with everything else on this list. Tools that already know about each other, rather than a vendor and a bill for each one. This is the build order, and only the first of them runs today.
- Monitor
Running, nothing to buy
Crashes and errors, uptime with certificate and domain expiry, cron and heartbeat checks, and status pages. Available for Flutter and Next.js. The free plan is open; nothing is purchasable.
- Analytics
Next, no code yet
Events, funnels, retention and dashboards on the same project Monitor already reads.
- Forms
Planned, no code yet
Form handling for the sites we build and the ones we maintain for other people. It exists on this list because we pay somebody else for it today, and a form endpoint is a small enough thing to own.
- CMS
Planned, no code yet
A client edits their own copy without being able to break the layout. One install, many client sites.
- Feature Flags and Remote Config
Planned, no code yet
Turn something on for some people, and change a value in a shipped app without shipping a new build.
No signup yet
Want an app on Monitor before signup opens?
Monitor has its own site, and it is the product rather than a description of one. Creating an account there takes one form and ends on a screen with your DSN on it. Billing is the last piece, so nothing on it can be paid for.
Tell us what you ship and roughly how much of it, and we will tell you honestly whether it is ready for you yet.
Every product on this page is being built by Unreal Ops. Monitor runs and takes real crashes; its free plan is open, nothing here can be bought, and nothing here has a customer. When that changes, this page changes with it.
Monitor, in its own words: what it stores and what it drops, how long it keeps it, what it cannot be relied on for, and who answers.