RoChartdocs

Alerts

Get told in Discord when players drop, servers stop or errors spike — checked every minute, compared with yesterday at this time — and again when it recovers.

An alert watches one number. When the number breaks your rule, the alert fires: you get a message, and another one when it's back to normal. Alerts in the sidebar shows every alert with its state, latest value and recent history.

Agent-first

Hand this to your agent. It looks at your game and proposes a few alerts worth having, then sets them up with you.

Game metrics

Game metric is the first choice in the alert form. Game metrics are computed from what your game servers send through the SDK, so they're live: you don't wait 1–2 days for the Creator Dashboard. Each one is checked every minute and compared with the same window yesterday at this time.

MetricThe numberWindow
Playing nowPlayers in a session right now (the same number as Live)right now
Servers runningServers that sent a heartbeat in the last 2 minutesright now
ErrorsScript errors ($error, counting grouped repeats)today, or the last 5 min – 6 h
Server crashesServers whose heartbeats stopped for 3+ minutes without a shutdowntoday, or the last N minutes
Players, New players, SessionsUnique players, first-time players, sessions startedtoday, or the last N minutes
Robux, Purchases, PayersFrom $purchasetoday, or the last N minutes
Playtime, Avg sessionHours played; average minutes per sessiontoday, or the last N minutes
D1 retentionYesterday's new players who have played today so fartoday

"Today" runs from midnight in your project's timezone up to now, and yesterday is cut at the same time of day. So a quiet morning isn't compared with a whole day.

The form has presets for the alerts most games want. Every number in a preset stays editable:

  • Players playing now drops below N: a floor under your concurrent players.
  • Playing now falls X% vs yesterday: catches a broken update before the evening peak.
  • No servers running: Servers running drops below 1. The game is down, or HTTP requests got switched off.
  • Errors in the last 15 minutes above N: a bad publish or a broken script.
  • Robux today below yesterday: Robux today falls 10% or more vs yesterday at this time.
  • New players in the last hour drops X%: discovery or a sponsored ad stopped bringing players in.

Messages read like Playing now: 744 (was 1,284, −42%) — falls 30% or more vs yesterday at this time.

Other things an alert can watch

WatchThe numberGood for
EventA count, unique players, or sum or average of a property, for the last complete hour, day or week. Live: the last 5 to 60 minutes, up to now. Filter on event properties to count only some, e.g. $server_type = publicYour own events: datastore_error, match_started
InsightA saved trend: its latest complete period. A saved funnel: its overall conversion %Tutorial completion
SQL queryA number from the first row of a saved queryAnything else

For SQL, sort so the row you care about comes first, for example ORDER BY day DESC. Event, insight and SQL alerts can be checked live (every minute), hourly, daily or weekly. To catch something in your own code, send an event when it happens, such as RoChart.trackServer("datastore_error", { key = "inventory" }), and alert when it goes above a few per 10 minutes.

When it fires

  • drops below or goes above a number;
  • changes by a percentage, going up, down or either way. Game metrics compare with the same window yesterday at this time. Event and trend alerts compare with the period before, and funnel and SQL alerts with the previous check.

The form shows the current value as you build the alert, and whether it would fire right now. A new alert checks once straight away.

Where you're told

Every check is recorded on the alert's page, and fires and recoveries appear in the activity log. Add up to five destinations:

  • Discord: paste a channel webhook URL (channel Settings → Integrations → Webhooks → New Webhook → Copy Webhook URL). It starts with https://discord.com/api/webhooks/. Alerts arrive as embeds: red when one fires, green when it's back to normal, with the value, yesterday's value, a link to the alert and a RoChart footer. If Discord rate-limits a message, RoChart waits as long as Discord asks and tries again.
  • Slack: paste an incoming webhook URL.
  • Telegram: add the RoChart bot to a channel or group, then enter its chat id. See Destinations → Telegram.
  • Webhook: RoChart sends a JSON POST you can point at an automation or an agent:
{
  "id": "alrt_4_fired_1762070412000",
  "type": "alert.fired",
  "alert": { "id": 4, "name": "Players dropped", "url": "https://app.rochart.co/p/1/alerts/4" },
  "project": { "id": 1, "name": "Lava Tycoon" },
  "value": 744,
  "previous": 1284,
  "period": "right now",
  "condition": { "type": "change", "percent": 30, "direction": "down" },
  "message": "Playing now: 744 (was 1,284, −42%) — falls 30% or more vs yesterday at this time",
  "at": "2026-11-02T18:00:12.000Z"
}

type is alert.fired, alert.resolved or alert.test. A recovery carries the same alert.id, so whatever started on the fire can close itself. Send test posts a test message to every destination. Destinations must be public https addresses. A failed delivery (no answer, 429 or 5xx) is tried twice more within about ten seconds, or after the wait Discord asks for.

Checking a webhook came from RoChart

Every webhook RoChart sends, from alerts and destinations, is signed in the Standard Webhooks format with your project's signing secret (Show signing secret under a webhook, in the alert or destination form):

  • webhook-id: the message id, the same on retries. Ignore ids you've already handled.
  • webhook-timestamp: when it was sent, in unix seconds.
  • webhook-signature: v1, and a base64 HMAC-SHA256 of <id>.<timestamp>.<body>.

The Standard Webhooks libraries check all three for you:

import { Webhook } from 'standardwebhooks'

const wh = new Webhook(process.env.ROCHART_WEBHOOK_SECRET) // whsec_…
const payload = wh.verify(rawBody, request.headers) // throws if it isn't from RoChart

Pause, check, delete

Switch an alert off to pause it. Check now runs it immediately and notifies you if its state changes. Editing what it watches or when it fires starts it fresh.

Agents

Agents can do all of this over MCP: create_alert, list_alerts, get_alert, update_alert, check_alert and delete_alert. A game alert is source: { kind: "game", metric: "playing_now" } with frequency: "live". Add windowMinutes for rolling metrics such as errors, and filters for platform, country or place version. A good pattern is to point a webhook at your agent, so a firing alert starts an investigation: "Players dropped 40% — which platform or place version changed?"

On this page