always-on performance monitoring for apps you vibe-coded
Sixty seconds to install. Sixty seconds to an answer.
You shipped a change. Something got slower, or a button stopped working, and nothing in your logs says why. Sixty is watching — every release, every day, whether or not you are — and it tells you in plain English which change did it. Then it hands the evidence to the coding agent you already have open, which fixes it.
- 1
- command to install
- 0
- dashboards to build
- 0
- thresholds to tune
- 0
- user data collected
You ship it. We catch it. Your agent fixes it.
There is no dashboard to check and no alert to configure. The three things below are the entire product, and you only do the first one.
You ship a change
It was fine on your laptop, against a small table, and the tests passed. Nothing about it looks dangerous — which is the problem.
We see the shape change
This release is compared against the last one. One query per render became fourteen. You configured no threshold, because there is none.
Your agent fixes it
The evidence goes over MCP to the coding agent you already have open — numbers, query, stack frames — and it writes the fix and records what it did.
The point is that it never stops.
Every release gets compared to the one before it, a couple of minutes after it goes out, for as long as the app is running. You do not start it, you are not asked anything, and there is no run to remember to do.
4c02f1ano drift · 47 operations compared2 minbb7e340no drift · 47 operations compared3 min2e9b503returns nothingprofile.load12 rows → 0 rows4 min5a1d0c8no drift · 48 operations compared2 minc40aa19no drift · 48 operations compared2 min9d3f01erowsorders.getUserOrders30 rows → 30,000 rows4 min9d3f01eN+1orders.enrichOrders1 query → 14 queries4 min7b21ee4no drift · 46 operations compared3 mina3f9c21no drift · 46 operations compared2 mind81b904no drift · 46 operations compared2 min
pnpm e2e run — those are its numbers — with illustrative revisions.Works with whatever you already have open.
Sixty does the watching; the coding agent you already use does the fixing. The handover between them is one MCP server, which is why the install is the same two values everywhere — and why building somewhere with no editor of your own is a prompt pasted into a chat instead.
Claude Code
One command. The findings arrive as a payload it can act on.
Cursor
The same two values as a config block.
Lovable
No editor of your own — paste one prompt into its chat.
Replit
Agent and deploys in one place; the release marker comes free.
VS Code
Copilot, Continue, or whatever else you have wired in.
Codex
And Windsurf, Zed, Cline — anything that speaks MCP.
Anything that speaks MCP works, including tools that did not exist when this was written. Nothing here needs a plugin from us, and nothing here is a partnership — it is one open protocol doing what it was for.
It didn't get slower. It changed shape.
This is why regressions reach your users. A query that returned 30 rows now returns 30,000 — on your laptop, against a small table, that barely moves the clock. It looks fine. Then real data arrives and it takes the app down.
Speed is a symptom and it shows up late. Shape is the cause and it shows up immediately, so that is what gets measured: rows returned per call, database calls per render, bytes per response.
pnpm e2e, which ships a deliberate regression and detects it, reproducible from a clean clone.14 queries where there was 1
The N+1 born inside a render. Each query is fast, so nothing looks wrong per request — only the count is wrong, and nothing else you can install will tell you.
30,000 rows to show 12
A query with no limit, or one that reads the whole table so your code can filter it afterwards. Fine on day one, fatal on day ninety.
A page that's slow only in Brazil
Real page timings per route — largest paint, interaction response, layout shift — broken down by country, so you find out it's a network problem and not your code.
An effect that never stops
A useEffect that sets state it also depends on, re-running forever. We catch it in two places: in your code before it ships, and in production as one endpoint suddenly called 300 times where it used to be called once.
Errors, including the ones that report success.
A crash is the easy case. The expensive ones return 200, log nothing, and leave somebody staring at a screen that does not work.
No orders yet
- status
- 200
- exceptions
- 0
- response time
- 84ms
- rows returned
- 12 → 0
The white screen
Client-side errors grouped by where in your code they happen, not by their message — so one bug is one finding instead of two hundred.
A button with no handler
Nothing throws, nothing is slow, the user clicks and leaves. Found by reading your code at build time, ranked by how much traffic the page actually gets.
It loads. It's empty.
A query that still succeeds and now returns no rows — the most common way one of these apps breaks, and the hardest to see.
Saved. Except it didn't.
A 401 or a 403 is not an error anything usually counts. The server declined and the person saw a form that submitted and did nothing.
Your users can see each other's data. Nothing errors.
A missing row-level security policy does not throw, does not get slower, and does not produce a support ticket from the person whose data leaked. It produces a page that works, for everybody, showing everything.
select * from orders where user_id = $124 rows returned — every customer's8 rows returned — only theirs
user_id, org_id or auth.uid() anywhere in it, handing back more rows than a lookup would.A query that never says which user
Three conditions have to hold at once before it says a word — a table that is per-user by name, no scoping condition anywhere in the statement, and enough rows coming back to rule out a lookup. Telling you your users can see each other's data is a serious thing to get wrong, so it asks you to confirm rather than asserting a leak.
A key that should never have shipped
A credential written into code the browser downloads. We report which kind it is and where, never the value. Your Supabase anon key is deliberately not flagged: it is meant to be public. The one that bypasses every permission rule in your database is not, and they look almost identical.
A wall of 401s that nobody is counting
Requests turned away at a rate they were not turned away at last release. Either your permissions changed and something legitimate is now locked out, or something is trying doors — and both are worth a look on the day rather than in a log nobody reads.
Postgres says exactly what went wrong. We read it.
A failed query is not one thing. Permission denied, a column that does not exist, and a duplicate email are three different problems with three different fixes, and every one of them arrives as a red line in a console nobody has open. The database distinguishes them by code. So do we.
Which means the finding your agent receives is not “this query failed”. It is the name of the defect, and that is the difference between an agent guessing and an agent fixing.
It's your row-level security
Not inferred from a 403 — quoted. Postgres returns 42501 when a policy refuses a statement, so the finding says a policy refused it, on which table, and how often. The most common way a published app locks out the people it was built for.
Your code asks for a column that isn't there
The migration was described in a chat and the frontend was written against the description. Postgres answers 42703, PostgREST answers PGRST204, and both mean the same thing: the code and the schema have come apart. This is the defect that generated apps have most often and that no amount of timing will find.
Everybody gets logged out, over the next hour
The background renewal that runs on a timer in every open tab is measured apart from somebody signing in, because they are not the same event. A sign-in failing is a support ticket. A refresh failing is every session in the world ending, quietly, as each one comes up for renewal.
Every message arrives nine times
A subscription opened in an effect with no teardown re-subscribes on every render. Nothing throws, nothing is slow, and the user watches each new message appear nine times while your connection count climbs toward the limit that will turn the feature off for everyone.
Uploads, by bucket
Failures and sizes per bucket — never per file, because in an app like this the filename is very often the user's own. Policies and limits are set per bucket anyway, so the bucket is the thing you can actually act on.
A 401 that isn't your fault
When the platform's gateway and the token your client holds disagree about a signing algorithm, every authenticated call to every edge function is refused. It looks exactly like your code being wrong. It is worth knowing within the hour that it isn't.
What it runs on
The browser half works with any backend, in any language — it watches the page, not your server. The server half is Node and Postgres today.
Working today
- Node.js
- TypeScript
- PostgreSQL
- React
- Next.js
- Vite
- Remix
- React Router
- SvelteKit
- Supabase
- Lovable
- Any front end
Not yet
- Python
- Ruby
- Go
- PHP
- Java
- Rust
- MySQL
- SQLite
- MongoDB
The right-hand column is a plan, not a promise, and it is ordered by what people ask for rather than by what is easiest. If yours is on it, the front-end agent already works for you today — and telling us which one moves it up.
From €14.99 a month.
Two plans, and both of them are the whole product — every finding, the agent API, and the MCP server. The only difference is how many apps you point it at. Both start with a 7-day trial: a card up front, and nothing charged if you cancel before it ends.
Solo
€14.99/month
1 app
The full product for a single app — all findings, the agent API, and the MCP server. Staging and preview deploys of the same app do not count as extra.
Studio
€49.99/month
5 apps
The same product across five apps — every finding, the agent API, and the MCP server. Staging and preview deploys of the same app do not count as extra, so five apps is five things you ship rather than five environments.
Staging and preview deploys of the same app are the same app — a one-app plan is not exceeded by instrumenting your staging environment, which is the thing we would most like you to do.
Already paying for something else? How this compares to Datadog, New Relic and Sentry — including the five kinds of team it is the wrong tool for.
Sixty seconds, honestly
You don't install this. Your coding agent does — and then it fixes what we find, in the same conversation. One command:
claude mcp add sixty \ -e SIXTY_API_KEY=sixty_sk_… \ -e SIXTY_ENDPOINT=https://ingest.sixty.sh \ -- npx -y @sixty-sh/mcp
Cursor, VS Code, Codex and anything else that speaks MCP take the same two values as a config block. Building on Lovable, with no editor of your own? Paste one prompt into its chat instead — sign in and it is written for you with your key already in it.
- 1
Say: install sixty in this project
It reads your repository, works out whether that means a Next config, a Vite plugin or a start command, and wires the agent in. Nobody has to know which shape this project is — the thing doing it can see.
- 2
Say: fix the worst finding
It pulls the evidence — the exact numbers, every stack frame, the query, and which child calls account for the change — writes the change, and records what it did on the finding so you can read it later.
- 3
Publish twice
Comparison is anchored to deploys, so the first finding arrives after your next one. The release marker comes from Vercel, Render, Railway, Fly or GitHub Actions on its own.
That last step is the honest catch. Install takes a minute; the first comparison takes as long as your next deploy, because there is nothing to compare a single release against.
It never learns anything about your users
No session IDs. No user IDs. No cookies. No recorded clicks or replays. No text from your pages, and no URLs — every address is reduced to its shape (/orders/:id) inside the browser, before anything is sent.
Query values never leave your app either: where email = 'alice@…' becomes where email = ? in your own process. What we receive is counts and distributions.
Which means there is something we genuinely cannot do: tell you who hit a bug. We can tell you what broke and how often. That is a deliberate trade, not a gap — and it is why installing this adds nothing to your consent banner. (We run analytics on this page, though, because we would like to know if any of this worked. Ours is at the bottom. It has a cartoon on it and a Reject that rejects.)
Find out what your last change did.
Watch it catch one
CloseReconstructed from the output of pnpm e2e, which seeds this exact regression and detects it. The numbers are that run's.
All quiet. No drift since your last deploy.
30 rows → 30,000 rows1000×
The query lost its where clause, so it reads the whole table and the code filters afterwards. Nothing got slower on your laptop — the table there has forty rows in it.
Waiting for somebody. It has been open for four seconds.Claimed by your agent — evidence pulled over MCP: the query, the stack frames, the numbers.Resolved · “added the missing where clause on user_id”
- You deploy
- We compare it to the last one
- Your agent takes it
- It closes itself