Advisors in Studio check your database for security and performance problems, check live health (error rates, connection pressure), and can alert you when health gets worse.
Open Advisors in Studio. The checks run when you open the page, cover the public schema and show each finding with the affected objects, an explanation, Copy SQL and Open in SQL editor. Some findings have a one-click Enable RLS or Add policy. The Advisors menu item shows how many tables have RLS turned off.
#Security
| Check | Level | What it finds |
|---|---|---|
| RLS disabled | Error | A table in public without Row Level Security: anyone with the anon key can read and change it. |
| View bypasses RLS | Error | A view without security_invoker, so it skips the policies of the tables it reads. |
| Sensitive columns exposed | Error | Columns named like password, secret, token, API key, private key, access key, SSN or card numbers that the API can read. |
| Anonymous writes allowed | Warning | A policy that lets anon insert, update or delete any row (true). |
| Materialized view in the API | Warning | Materialized views have no RLS, so every row is readable. |
| Mutable search_path | Warning | A function without a fixed search_path. |
| Realtime without RLS | Warning | A table that sends realtime changes but has RLS off, so every subscriber receives every row. |
| RLS without policies | Info | RLS is on but no policy exists, so the API returns no rows. |
#Performance
| Check | Level | What it finds |
|---|---|---|
| No primary key | Warning | Tables without a primary key are slow to update and can't be edited in the Table Editor. |
| Unindexed foreign key | Warning | A foreign key without an index slows down joins and deletes. |
#Health
The Health tab checks how your project is running right now, not how it is built. It reads the API request log of the last two hours, Edge Function calls, the database's live sessions and the pooler charts. An error rate counts only when it is above normal: at least the threshold, with at least 20 requests, and at least twice the hour before. A rate at or above the error level is always reported, so a long outage still shows.
| Check | Warning at | Error at | What it finds |
|---|---|---|---|
| REST API error rate | 5% | 20% | Share of /rest/v1 requests that answered 5xx in the last hour |
| Auth error rate | 5% | 20% | Share of /auth/v1 requests that answered 5xx |
| Failed sign-ins above normal | 30% | 60% | Share of sign-in requests (/auth/v1/token) that failed |
| Storage error rate | 5% | 20% | Share of /storage/v1 requests that answered 5xx |
| Edge Functions error rate | 5% | 20% | Share of function calls that failed |
| Database connections near the limit | 80% | 95% | Connections in use against your plan's connection limit, now |
| Pooled client connections near the limit | 80% | 95% | Pooler clients against your plan's limit, last 5 minutes |
| Clients waiting for a pooled connection | 1 client | 10 clients | Clients that wait for a free pooled connection, last 5 minutes |
Each finding shows the measured value, the hour before, the threshold and one next step. The thresholds are the same ones your monitoring agent uses, so Studio and the agent agree on what counts as above normal.
#Health alerts
Health alerts run the health checks every 5 minutes for you, without an agent. They are off by default. On the Health tab, owners and admins choose Turn on health alerts, then pick where alerts go:
- E-mail the project owner (on by default).
- Project webhooks: the events
health.alertandhealth.recovered, to every webhook that chose them. - Telegram: a chat id (for example
-1001234567890or@channel) and your own bot token from @BotFather. The token is stored sealed and never shown again. - Tell me when it is back to normal: one notice when a finding clears.
You get an alert when a finding is new or gets worse (warning to error), not again while it stays the same. At most 12 alerts per project are sent in an hour. Send a test alert checks your channels. Turning alerts on and off and every change is written to the audit log.
{
"type": "health.alert",
"record": {
"id": "health:rest_error_rate",
"title": "REST API error rate above normal: 7.4% in the last hour",
"level": "warn",
"service": "rest",
"measured": { "value": 7.4, "unit": "%", "events": 540, "errors": 40, "window": "1h" },
"baseline": { "value": 1.2, "unit": "%", "events": 495, "errors": 6, "window": "previous 1h" },
"threshold": { "value": 5, "error_at": 20, "unit": "%", "window": "1h", "compare": "previous_hour", "factor": 2, "min_events": 20 },
"next_step": "Open Logs › API with status 5xx and the path /rest/v1 ...",
"url": "https://stitchdb.com/dashboard/project/<ref>/advisors?tab=health"
}
}#From the API
curl "https://stitchdb.com/platform/v1/projects/<ref>/advisors?type=health" \
-H "Authorization: Bearer $STITCHDB_ACCESS_TOKEN"type is security, performance, health or all (default); /advisors/<type> works too. The answer has findings (each with id, lint, category, level, title, detail, fix_sql where there is one, and a docs link) and lints, the list of every check. It needs the database:read scope. See the Management API.
AI tools connected over MCP can read the same findings with get_advisors.