# DataRunner > Scheduled SQL reporting, as a web console > (SaaS). You connect a database and describe what you want in plain language; > an AI model (included in every plan, or your own Claude, GPT or Gemini key) > reads the schema and proposes the query, the cron expression and the timezone, which > you review before anything is created. DataRunner then runs the SQL, formats > the result and delivers it by email, chat or webhook. It also > watches the health of every connected database, opens incidents when one goes > down, and carries dashboards, alert routes and recipient lists in the > same console. Site: https://www.datarunner.app/ Console: https://console.datarunner.app Languages: English (/en), Brazilian Portuguese (/pt) Contact: projeto@datarunner.app (support, sales, security and privacy) Full documentation as one text file: https://www.datarunner.app/llms-full.txt ## What it actually does - **AI assistant.** Included in every plan as a monthly request quota (30 on Solo, 300 on Pro, 1,500 on Team, 5,000 on Business, with a per-person daily limit). A workspace can instead connect its own Anthropic (Claude), OpenAI (GPT) or Google (Gemini) key; usage is then billed by the provider and the plan quota no longer applies. Every request is recorded in the workspace's assistant history. The model receives the request and the schema of the chosen connection — table names, column names, types and the column descriptions written on the connection — never rows of data. It returns SQL; with the per-workspace `ai_autoconfigure` flag on, it also returns a cron expression, the timezone for that schedule and a report name. Operational requests come back as a monitor and an alert route. Everything arrives as a proposal that a human approves item by item, and every proposed action is checked against the caller's workspace permissions before it applies. The assistant is optional; everything else works without it. - **Connections.** 20 database kinds, all of which execute queries: PostgreSQL, MySQL, SQL Server, SQLite, MariaDB, Redshift, CockroachDB, TimescaleDB, Greenplum, Oracle, ClickHouse, BigQuery, DuckDB, MotherDuck, Trino, Presto, Firebird, Snowflake, Databricks and Amazon Athena (Snowflake, Databricks and Amazon Athena marked beta). - **Queries.** SQL workbench with syntax highlighting, autocomplete, `{{...}}` parameters bound as real driver parameters, per-save versioning, and a cost estimate for engines that bill by data scanned. - **Schedules.** Cron expressions with a timezone per schedule, not per workspace. Run history records duration, row count and errors. - **Reports and delivery.** Output as CSV, Excel (XLSX), PDF or inline HTML. 7 delivery channels: Email, WhatsApp (beta), Telegram, Generic webhook, Slack, Discord and Google Sheets. Delivery rules can skip an empty result or escalate past a row threshold. - **Database monitor.** Availability, latency and connection metrics for every connected database. Incidents open and close themselves and show which schedules depend on the database; alert routes decide which channel the warning lands on. A bridge agent reaches databases on private networks, outbound only, limited to the addresses allowed on that machine. - **Dashboards.** Grids of widgets, each fed by a saved query and drawn as one of thirteen shapes: table, number, line, area, bar, pie, scatter, histogram, gauge, heatmap, combo, treemap or funnel. Public links with optional password and expiry, and an embeddable iframe. Column masking applies on the dashboard exactly as it does in the editor. - **Recipients.** Contacts with an e-mail, WhatsApp or Telegram channel, segmented lists that are re-evaluated on every send, and scoped unsubscribes. A report goes to a loose address, a contact or a list. - **Governance.** Roles with per-resource permissions, passkeys and two-factor auth, audit logs, column masking policies, scoped API keys, data export and account deletion from the console. ## Pricing - Solo — R$0/month or $0/month. 1 user · 1 connection; 3 schedules · 500 queries/month; 500 e-mails/month · 5,000 rows per query; 1 database monitor; Checks every 5 min; 100 contacts · 2 dashboards; 14 days of history; 30 included AI requests/month · 100 e-mails without your own provider. - Pro — R$79/month or $19/month, or R$790/year (2 months free). 3 users · 5 connections; 20 schedules · 3,000 queries/month; 5,000 e-mails/month · 50,000 rows per query; 5 database monitors; Checks every 2 min; 1,000 contacts · 10 dashboards; 90 days of history; 300 included AI requests/month · 1,000 e-mails without your own provider. - Team — R$197/month or $49/month, or R$1,970/year (2 months free). 10 users · 25 connections; 100 schedules · 50,000 queries/month; 50,000 e-mails/month · 1,000,000 rows per query; 50 database monitors; Checks every 60 s; 10,000 contacts · 25 dashboards; 1 year of history; 1,500 included AI requests/month · 5,000 e-mails without your own provider. Everything in Pro, plus API keys and alert routes. - Business — priced on request. 50 users · 100 connections; 500 schedules · 500,000 queries/month; 500,000 e-mails/month · 10,000,000 rows per query; 500 database monitors; Checks every 15 s; 100,000 contacts · 200 dashboards; 3 years of history; 5,000 included AI requests/month · 20,000 e-mails without your own provider. Everything in Team, plus audit logs and priority support. Billed through Stripe in Brazilian reais (BRL), or in US dollars outside Brazil — the checkout picks the currency by country. Monthly, or yearly in one payment with two months free. Business is quoted per company and invoiced. Every plan includes every connector; the plan sets volume, not features. No credit card is needed for Solo, and it does not expire. ## Apps - Web console — the complete product, in a browser. - Agent — Windows and Linux, x86-64 and ARM64, Native AOT, push-only. It holds no database credentials and accepts no remote command. - CLI — scripts the same API from a terminal or a CI job. ## What DataRunner is not - Not a BI platform. Dashboards exist, but there is no drag-and-drop chart builder: every widget is fed by a SQL query, written by you or by the assistant. - Not an ETL platform. Nothing transforms data between warehouses, and there is no dimensional modelling. - Not an AI product with a model of its own. The assistant is optional and runs on a key you supply; no output is applied without a human approving it. ## Documentation - [Getting started](https://www.datarunner.app/en/docs/getting-started): From signup to the first delivered report, in the order the screens appear. - [Connections](https://www.datarunner.app/en/docs/connections): Which databases are supported, what each one can actually do, and how credentials are stored. - [Queries](https://www.datarunner.app/en/docs/queries): The SQL workbench, parameters, versions, and what happens when a result is too large. - [AI assistant](https://www.datarunner.app/en/docs/assistant): The AI included in the plan or your own model, asking in plain language, and what the product lets the answer touch. - [Schedules](https://www.datarunner.app/en/docs/schedules): Cron, per-schedule timezones, run history, and what happens when a run fails. - [Reports and delivery](https://www.datarunner.app/en/docs/reports): Output formats, recipients, and the rules that decide whether a send happens at all. - [Channels](https://www.datarunner.app/en/docs/channels): The seven delivery destinations, what each one needs, and what each one can carry. Each has its own page with the setup, the fields and how to test. - [Command line](https://www.datarunner.app/en/docs/cli): Install the DataRunner command line, authenticate, and turn a query into a build step. - [Database monitor](https://www.datarunner.app/en/docs/monitors): The health of every connected database: what is checked, the metrics that come with it, and how an incident starts. - [Bridge to a private network](https://www.datarunner.app/en/docs/bridge): How to query a database only your network can reach, without opening a firewall port. - [Alerts and routes](https://www.datarunner.app/en/docs/alerting): Where the notice of a database going down, or of a rule that fired, goes. - [Security and data](https://www.datarunner.app/en/docs/security): Encryption, roles, authentication, audit, and what you can export or delete. - [Dashboards and sharing](https://www.datarunner.app/en/docs/dashboards): Panels built from queries, per-dashboard filters, public links with password and expiry, and the iframe. - [Recipients](https://www.datarunner.app/en/docs/contacts): Who receives a report: contacts, lists with segments, and unsubscribes. - [API, keys and outbound webhooks](https://www.datarunner.app/en/docs/api): The browsable reference, how to authenticate with a key, and the events the product pushes to your endpoint. - [Plans, billing and account](https://www.datarunner.app/en/docs/billing): Monthly or yearly, what happens when the card fails, extra workspaces, ownership and a confirmed e-mail. - [Email](https://www.datarunner.app/en/docs/channel-email): Wiring up Email: what to create at the provider, what to paste here, what goes in Target, and how to test before depending on it. - [WhatsApp](https://www.datarunner.app/en/docs/channel-whatsapp): Wiring up WhatsApp: what to create at the provider, what to paste here, what goes in Target, and how to test before depending on it. - [Telegram](https://www.datarunner.app/en/docs/channel-telegram): Wiring up Telegram: what to create at the provider, what to paste here, what goes in Target, and how to test before depending on it. - [Generic webhook](https://www.datarunner.app/en/docs/channel-webhook): Wiring up Generic webhook: what to create at the provider, what to paste here, what goes in Target, and how to test before depending on it. - [Slack](https://www.datarunner.app/en/docs/channel-slack): Wiring up Slack: what to create at the provider, what to paste here, what goes in Target, and how to test before depending on it. - [Discord](https://www.datarunner.app/en/docs/channel-discord): Wiring up Discord: what to create at the provider, what to paste here, what goes in Target, and how to test before depending on it. - [Google Sheets](https://www.datarunner.app/en/docs/channel-google_sheets): Wiring up Google Sheets: what to create at the provider, what to paste here, what goes in Target, and how to test before depending on it. ## Ready-made SQL queries - [PostgreSQL health](https://www.datarunner.app/en/templates): [Dead tuples by table](https://www.datarunner.app/en/templates/postgres/dead-tuples), [Indexes never used](https://www.datarunner.app/en/templates/postgres/unused-indexes), [Transactions open for more than 5 minutes](https://www.datarunner.app/en/templates/postgres/open-transactions), [Sessions waiting on a lock](https://www.datarunner.app/en/templates/postgres/lock-waits), [Statements by total time](https://www.datarunner.app/en/templates/postgres/slowest-statements), [Largest tables](https://www.datarunner.app/en/templates/postgres/largest-tables), [Cache hit ratio](https://www.datarunner.app/en/templates/postgres/cache-hit), [Connections by state](https://www.datarunner.app/en/templates/postgres/connections-by-state), [Sequences past 80% of their range](https://www.datarunner.app/en/templates/postgres/sequences-near-limit), [Replication lag](https://www.datarunner.app/en/templates/postgres/replication-lag) - [MySQL health](https://www.datarunner.app/en/templates): [Largest tables and their free space](https://www.datarunner.app/en/templates/mysql/table-sizes), [Tables without a primary key](https://www.datarunner.app/en/templates/mysql/tables-without-pk), [Queries running for more than 60 seconds](https://www.datarunner.app/en/templates/mysql/long-queries), [Statements by total time](https://www.datarunner.app/en/templates/mysql/slowest-statements), [Indexes never used](https://www.datarunner.app/en/templates/mysql/unused-indexes), [Connections by command](https://www.datarunner.app/en/templates/mysql/connections-by-command), [InnoDB buffer pool hit ratio](https://www.datarunner.app/en/templates/mysql/buffer-pool) - [SQL Server health](https://www.datarunner.app/en/templates): [Blocked sessions](https://www.datarunner.app/en/templates/mssql/blocking), [Missing indexes the optimiser asked for](https://www.datarunner.app/en/templates/mssql/missing-indexes), [Indexes written to but never read](https://www.datarunner.app/en/templates/mssql/unused-indexes), [Queries by total CPU](https://www.datarunner.app/en/templates/mssql/top-cpu-queries), [Top waits since restart](https://www.datarunner.app/en/templates/mssql/wait-stats), [Largest tables](https://www.datarunner.app/en/templates/mssql/table-sizes), [Sessions by status](https://www.datarunner.app/en/templates/mssql/sessions-by-status) ## Pages - [Home](https://www.datarunner.app/en): what DataRunner does, plans and FAQ - [Download](https://www.datarunner.app/en/download): bridge agent and CLI - [Changelog](https://www.datarunner.app/en/changelog): release notes - [Blog](https://www.datarunner.app/en/blog): product notes - [Coming from PopSQL](https://www.datarunner.app/en/popsql): PopSQL has been in limited support since 2025-09-02; its shutdown, announced for 2026-09-01, was postponed on 2026-08-11 with no new date, and PopSQL promises at least 90 days of notice. Importing its queries, and what maps to what - [Redash alternative](https://www.datarunner.app/en/alternatives/redash): importing Redash queries with their parameters, what maps to what, and what does not come across - [Metabase alternative](https://www.datarunner.app/en/alternatives/metabase): importing native SQL questions, what maps to what, and the gaps (no visual builder, no embedding) - [Free Postgres health check](https://www.datarunner.app/en/tools/postgres-health): one read-only query, pasted result analyzed in the browser: unused indexes, dead rows, stuck transactions, sequences near their limit - [About](https://www.datarunner.app/en/about): why the product exists - [Contact](https://www.datarunner.app/en/contact): support, sales, privacy and security - [Privacy policy](https://www.datarunner.app/en/privacy) - [Terms of service](https://www.datarunner.app/en/terms) Portuguese versions live under /pt with the same paths. --- # Getting started Source: https://www.datarunner.app/en/docs/getting-started From signup to the first delivered report, in the order the screens appear. ## The idea in one sentence You save a connection, write a query, and attach a schedule to it. On every trigger DataRunner runs the SQL, formats the result and delivers it through the channels you pointed at. The database monitor and the alerts exist so you find out when that path breaks. ## The whole path 1. Create an account at console.datarunner.app. The workspace is created with it and you own it. 2. Under Connections, add your database. Test the connection before saving: the test runs a trivial SELECT and tells you exactly what failed. 3. Under Queries, write the SQL and run it once. The result appears below, with the row count and duration. 4. Save the query and attach a schedule: cron expression, timezone and output format. 5. Point at least one delivery channel. With no channel the run still happens, but the result stays in the history. > The free plan (Solo) allows one connection, three schedules and five hundred queries a month. That is enough to put a real report into production before deciding anything. ## Knowing it worked Every trigger writes a line into the query history, with start time, duration, row count, and the error when there was one. Delivery writes its own receipt: the channel, the destination, and the answer it gave. If the email did not arrive, the receipt says whether it left here. - Run history: what the database answered. - Delivery receipts: what each channel answered. - Failure alerts: who was told, and when. --- # Connections Source: https://www.datarunner.app/en/docs/connections Which databases are supported, what each one can actually do, and how credentials are stored. ## Two levels of support Not every connector does the same thing, and the difference changes what you can build on top of it. There are two levels, and the new-connection screen shows which one an engine is at. | Level | What you can do | | --- | --- | | Query + schema | Reports, schedules, autocomplete and table browsing | | Query | Reports and schedules; no autocomplete | - PostgreSQL: query, query + schema - MySQL: query, query + schema - SQL Server: query, query + schema - SQLite: query, query + schema - MariaDB: query, query + schema - Redshift: query, query + schema - CockroachDB: query, query + schema - TimescaleDB: query, query + schema - Greenplum: query, query + schema - Oracle: query - ClickHouse: query - BigQuery: query - DuckDB: query - MotherDuck: query - Trino: query - Presto: query - Firebird: query - Snowflake: query (beta) - Databricks: query (beta) - Amazon Athena: query (beta) > Snowflake, Databricks and Amazon Athena are marked beta: the provider is written and compiles, but has never been exercised against a live instance. The first real run will be yours, and we would rather say so than find out alongside you. ## Credentials - Credentials are encrypted with AES-GCM before they touch the database, and the key does not live in the same table. - The connection to your database uses TLS when the server offers it; hostless engines such as BigQuery, Athena and Snowflake authenticate through their own SDK. - A password is never returned by the API after it is saved. On edit the field is blank and is only rewritten if you type something. ## Plan limits | Plan | Connections | Queries per month | Rows per query | | --- | --- | --- | --- | | Solo | 1 | 500 | 5,000 | | Pro | 5 | 3,000 | 50,000 | | Team | 25 | 50,000 | 1,000,000 | | Business | 100 | 500,000 | 10,000,000 | --- # Queries Source: https://www.datarunner.app/en/docs/queries The SQL workbench, parameters, versions, and what happens when a result is too large. ## The workbench The workbench is a SQL editor with syntax highlighting and autocomplete fed by the connection schema, on the engines that expose one. Running it once shows the result, the duration and the row count, and it is what you should do before scheduling anything. ## Parameters A parameter is written in double braces and becomes a real driver parameter, not string concatenation. That is what stops a value containing a quote from becoming SQL injection. revenue_by_region.sql: ``` SELECT region, sum(total) AS revenue FROM orders WHERE day >= {{start}} AND day < {{end}} GROUP BY 1 ORDER BY 2 DESC ``` The schedule sets each parameter value. Values relative to the run date are resolved in that schedule’s timezone, not the server’s. ## Versions Every save keeps the previous version with its author and date. You can compare two versions and restore one. It is the answer to the question that always follows a strange number in a report: what did this query do last month. ## When the result is large - The row ceiling per query comes from the plan. On hitting it the run stops and the report is marked truncated, rather than delivering half a set without saying so. - There is a time limit per run; a query that exceeds it is cancelled at the database, not abandoned. - For engines that bill by data scanned, the workbench shows a cost estimate before you run. --- # AI assistant Source: https://www.datarunner.app/en/docs/assistant The AI included in the plan or your own model, asking in plain language, and what the product lets the answer touch. ## Included AI or your own key Every plan comes with AI requests each month: 30 on Solo, 300 on Pro, 1,500 on Team and 5,000 on Business. Each person can make up to 20 requests a day, and in a workspace with more than one person nobody can use more than half of the month. The counter is under Settings → Billing. If you prefer, connect your own Anthropic (Claude), OpenAI (GPT) or Google (Gemini) account under Settings → Integrations. Usage is then billed to you by them directly, and the plan quota stops applying. The key is encrypted at rest like any database credential. - More than one provider can be connected; the card says which one is answering, because three "connected" badges would read as three independent facts, and the assistant calls exactly one. - The model field takes a specific id. Left empty, the catalogue default applies. Swapping the id is how you follow a new model without waiting for a release of ours. - The "Test" button makes a real call to the provider and shows what it said. A revoked key fails here rather than halfway through a request. - If you do not use the assistant, the rest of the product works the same. ## What leaves here Your request and the structure of the chosen connection: table names, column names, types, and any descriptions you wrote on the columns of the connection. Rows from your data are not sent. The call goes from our server to the provider (Anthropic for the included AI, or the one you connected). Each request and its reply are kept in the workspace's assistant history, with who asked and what was applied. > The quality of the SQL rests almost entirely on that structure. PostgreSQL, MySQL, SQL Server and SQLite connections have introspection, so the model can see the schema; on the other engines it writes blind, and the query is worth reading line by line before you schedule it. ## Asking for a query In the workbench, open Tools → AI and describe what you want to see. "Generate SQL" streams the query back as it is written, with an explanation and warnings when the output contains a destructive verb. "Replace editor SQL" moves the result into the editor, where it is yours to review, run and save like any other. A request carrying everything the proposal needs: ``` Read the database: weekly revenue by region, with the change against the week before. Every Tuesday at 10am, São Paulo time. ``` The five things that sentence carries are the five that come back: the data, the cut, the comparison, the cadence and the timezone. It works the other way too: drop the Tuesday and no cron comes back, drop "São Paulo time" and no timezone does. The model does not invent a schedule nobody asked for, and when the timezone is missing the card says so: the workspace default applies, never UTC. ## Asking for the schedule too With the flag on, the same request comes back with more than SQL: the cron expression, the timezone for that schedule, the model’s own plain-language reading of the cron, and a name for the report. None of it is applied; the screen shows a proposal and a button. Wrong SQL shows a wrong number on one screen and somebody notices; a wrong cron delivers to real recipients on a timetable nobody chose, and the first to find out is a recipient. 1. Settings → Feature flags → turn on "ai_autoconfigure". It starts off in every workspace on purpose: widening what a model’s output may touch is the tenant’s call, not ours. 2. In the workbench, write the request and use "Propose schedule too". 3. Check the cron against the plain-language reading beside it. That reading is what lets a human validate the expression without parsing cron. 4. "Apply and schedule" creates the schedule and, when none exists yet, the report that will deliver it. The notice says so rather than letting you find a report you never asked for. ## The things that are not SQL Ctrl/⌘ I opens the assistant from any screen. There the request is about the workspace, and the answer is a plan of actions, each with the reason it is there and a checkbox that decides whether it happens. The catalogue is closed: the model cannot even describe an action the product does not know how to execute. | Action | What for | | --- | --- | | Monitor | something reachable or not: a URL, a port, a certificate, a database, or a job that should have checked in | | Alert route | where an alert goes once it fires: which channel, in what order, after what delay | | Schedule | a query that starts running on its own | | Open screen | when the request already has an answer on a screen that exists, and creating anything would be wrong | > Every action carries the permission it requires, checked against your workspace role before it is applied. A viewer gets the plan and cannot apply it, because the same limit applies here as everywhere else. ## Where else it shows up - Dashboards: describe the board and the model picks the widgets, the chart for each and which of your saved queries feeds them, and says so when none fits. - Connection context: the model reads the schema and writes what that database is: the domain, the tables that matter, how they join. It is the only AI output in the product that can be saved without field-by-field approval, because the worst case is a bad paragraph somebody fixes. It stays editable: the model reads structure, not intent. --- # Schedules Source: https://www.datarunner.app/en/docs/schedules Cron, per-schedule timezones, run history, and what happens when a run fails. ## The expression A schedule is a five-field cron expression. The minimum interval depends on the plan: five minutes on Solo, two minutes on Pro, sixty seconds on Team, fifteen seconds on Business. Examples: ``` 0 8 * * 1-5 every weekday morning at 08:00 0 */15 * * * every 15 minutes 30 23 L * * 23:30 on the last day of the month ``` ## Timezone The timezone belongs to the schedule, not the workspace. The workspace only supplies a default so the field arrives filled in; from there each schedule carries its own. That is what lets the same report go out at 08:00 in São Paulo and 08:00 in Lisbon without duplicating the query. > UTC is never chosen silently. If a schedule is in UTC, it is because somebody picked UTC. ## History Every trigger records start time, duration, rows returned and the error when there was one. History is kept for the plan’s retention: 14 days on Solo, 90 days on Pro, one year on Team, three years on Business. ## When it fails - The run is marked failed with the message the database returned, unrewritten. - The schedule stays active; one failure does not switch a report off. - If a failure alert is configured, it fires through the workspace’s alert route. --- # Reports and delivery Source: https://www.datarunner.app/en/docs/reports Output formats, recipients, and the rules that decide whether a send happens at all. ## Formats | Format | When to use it | | --- | --- | | Inline HTML | A few rows that need reading on a phone, without opening an attachment | | CSV | Input for another system, or a large volume | | Excel (XLSX) | The recipient will filter, sum and paste it somewhere else | | PDF | The document has to look the same for everyone who opens it | ## Recipients A report destination is a loose address, a contact, or a broadcast list, and the contact or list is resolved again on every send, so whoever joins the list afterwards starts receiving it. Which channel carries a recipient follows from the kind of address they have; when the workspace holds more than one account of a kind (two WhatsApp Business numbers, say), the list picks which one it goes out on, and everything else falls back to the default account. Addresses that returned a hard bounce go onto the suppression list and stop being retried. ## Delivery rules The rule decides whether the send happens, based on that run’s result. It is what separates a report from an alert, and what stops somebody’s inbox receiving thirty empty messages a week until it becomes a filter. - Skip the send when the result comes back empty. - Send only above a row count. - Escalate to another channel past a threshold. --- # Channels Source: https://www.datarunner.app/en/docs/channels The seven delivery destinations, what each one needs, and what each one can carry. Each has its own page with the setup, the fields and how to test. ## What exists | Channel | Configuration | Carries attachments | | --- | --- | --- | | Email | The workspace SMTP server, or ours; sender verifiable by domain | Yes | | WhatsApp | Meta’s WhatsApp Cloud API: phone number id, access token, and the template they approved | Yes, when the approved template declares a DOCUMENT header | | Telegram | Bot token, and the destination’s numeric chat id; the bot has to be in the group or chat | Yes, sent as a document with the text as its caption | | Webhook | URL, optional headers, and a secret for signing | Yes, the body is the result | | Slack | Incoming webhook URL; a bot token with files:write for uploads | Only with a bot token | | Discord | Webhook URL of the channel | No; it sends a summary and link | | Google Sheets | Service account and spreadsheet id; share the spreadsheet with the service account as Editor | No; it writes rows to a tab | - [Email](/docs/channel-email) - [WhatsApp](/docs/channel-whatsapp) - [Telegram](/docs/channel-telegram) - [Webhook](/docs/channel-webhook) - [Slack](/docs/channel-slack) - [Discord](/docs/channel-discord) - [Google Sheets](/docs/channel-google_sheets) > The WhatsApp integration uses Meta’s official Cloud API. Messages outside the 24-hour window need a template they approved. That rule is Meta’s. On Telegram, a bot only reaches whoever messaged it first: the destination is the numeric chat id, and a person’s @name is not addressable by the Bot API. ## Test before depending on it Every channel has a test button that validates the credentials against the provider without sending a message, and records the outcome: date, status, and the provider’s error when there was one. A channel that has never been tested is flagged in the list. To check delivery end to end, run the report: the run log says which channel each recipient went through and what the provider answered. ## Webhook signature When you set a secret, every POST carries an HMAC-SHA256 signature of the body in a header. Verify it before processing: without that, anyone who discovers the URL can inject a fake report into your system. --- # Command line Source: https://www.datarunner.app/en/docs/cli Install the DataRunner command line, authenticate, and turn a query into a build step. ## Install A single self-contained binary. The machine needs nothing installed first, neither a runtime nor a package manager. That is what makes it usable in a lean CI image. Linux and macOS: ``` curl -fsSL https://api.datarunner.app/downloads/cli/install.sh | bash ``` Windows: ``` irm https://api.datarunner.app/downloads/cli/install.ps1 | iex ``` > Neither asks for root or administrator: it installs into a user directory and adjusts that user PATH. The installer verifies the published SHA256 before installing and refuses on a mismatch. Pin the version in CI. A job that resolves “latest” on every run changes behaviour without anybody making a commit. ``` curl -fsSL https://api.datarunner.app/downloads/cli/install.sh | bash -s -- --version 0.1.1 ``` ## The first five minutes After installing, this is a whole session end to end. The step that usually goes missing is the second one: a query has an id, and listing is the only place it comes from. 1. Log in, once per machine. The key comes from Settings → API keys in the console, and is only shown at the moment you create it. The command asks for it without echoing, so it never goes through the command line or into shell history. 2. List what exists in the workspace. This is where the id the other commands want comes from. 3. Run a query and look at the result. 4. Turn that query into a check the build understands. 1 · log in: ``` datarunner auth login → chave: •••••••••••••••••••••••• ✔ servidor respondeu api.datarunner.app • 84 ms ✔ chave aceita you@acme.com • admin • Acme ✔ perfil 'default' salvo cifrado para este usuário do Windows (DPAPI) ``` 2 · see what exists: ``` datarunner query list id nome conexao atualizada ──────────────────────────────────── ─────────────── ────────── ────────────── 3f2a91c4-8e17-4b2a-9f03-1d5c7e8a2b60 Monthly revenue Postgres 2026-09-01 14:22 a7c04e12-3b95-4d81-b6ef-92a10c4d7f38 Orphan orders Postgres 2026-08-28 09:10 ``` 3 · run it: ``` datarunner query run 3f2a91c4-8e17-4b2a-9f03-1d5c7e8a2b60 month total ────────── ───────── 2026-07 184320.50 2026-08 201455.00 2 linha(s) em 340ms. ``` 4 · make it a build check: ``` datarunner query assert a7c04e12-3b95-4d81-b6ef-92a10c4d7f38 --expect-empty ok — 0 linha(s) em 120ms. ``` > That last command exits 0 when no row came back and 1 when one did. That, and only that, is what stops the build when data integrity broke. ## Credential The key comes from Settings → API keys. Its scopes narrow what the tool reaches on top of the role of whoever created it: a restricted key stays restricted even when it belongs to an admin, and a key never grants platform-wide powers. On your machine: asks for the key without echoing: ``` datarunner auth login datarunner auth login --url https://datarunner.yourcompany.com # self-hosted ``` In CI: nothing is written to disk: ``` export DATARUNNER_URL=https://api.datarunner.app export DATARUNNER_KEY=dr_... ``` > To run queries in CI, tick the run:queries scope. It already includes reading and cannot change anything. Listing queries and executing SQL against a production database are different powers, so read:queries alone does not run. API keys are available from Team up, so the command line is too; Solo and Pro do not have it. ## A query as a build step A query that lists orphaned rows is something anybody can write today and cannot enforce anywhere. With the command below it becomes a build step: if a migration broke referential integrity, the build fails instead of production finding out later. ``` datarunner query assert 3f2a... --expect-empty ``` | Check | Fails when | | --- | --- | | --expect-empty | any row came back | | --expect-rows | the count is not exactly that | | --min-rows | fewer than that came back | | --max-rows | more than that came back | > If the result hits the plan row cap, the check fails rather than passes. A truncated count is not a count, and an --expect-empty that passes because the cap hid the rows is worse than no check at all, because somebody is relying on it. ## Every command | Command | What it does | Key scope | | --- | --- | --- | | auth login \| list \| use \| logout | stores and switches credentials | — | | whoami | checks the current credential | — | | query list | lists queries, with the id | read:queries | | query run | runs and prints | run:queries | | query assert | runs and checks; exits 1 on failure | run:queries | | monitor list \| status | monitor state | read:monitors | | connection list | lists connections | read:connections | Every command has its own help: datarunner help query, datarunner help monitor, and so on. datarunner help ci prints a ready CI file. > run:queries already includes reading, so a CI key that only checks data needs nothing else. Listing queries and executing SQL against a production database are different powers, which is why read:queries alone does not run anything. ## Working with more than one environment The first thing anybody does with this is point it at staging and then at production. Profiles exist so that switch is not another login. ``` datarunner auth login --url https://api.acme.dev --profile dev datarunner auth login --url https://api.acme.com --profile prod datarunner auth use prod datarunner query list --profile dev # without switching the current one ``` The file lives at ~/.datarunner/config.json. On Windows the key is sealed with DPAPI for your user: the file copied to another machine, another account or a backup does not open. On Linux and macOS, mode 600 in a 700 directory. Logout removes the profile from your machine; the key stays valid on the server until somebody revokes it in the console. ## Interactive mode Type just datarunner in a terminal. The opening screen connects to the server and shows who you are and which workspace you are in; then a prompt takes the same commands without the prefix. Scripts and CI see no change: with no terminal, the bare binary still prints the help and exits 2. ``` datarunner:prod › query run Monthly rev⇥ datarunner:prod › query run 3f2a91c4-8e17-4b2a-9f03-1d5c7e8a2b60 → Monthly revenue (3f2a91c4) ``` - Tab completes commands, options and ids by name. The list comes from the API, with your key's permissions. - Wherever a command takes an id, a name or the start of the id works too, in and out of interactive mode. If it matches more than one, the CLI refuses and lists them instead of picking. - Ctrl+C stops the running command, not the shell. History lives in memory only and never keeps a line carrying a key. ## AI agents (MCP) The CLI is also an MCP (Model Context Protocol) server. Claude Desktop, Claude Code, Cursor and Windsurf get to see the workspace: connections, schemas, saved queries, read-only SQL, monitors and alerts. The agent can do at most what the key can, because permissions are checked on the server, exactly as for the console. Connect in one command: ``` datarunner auth login datarunner mcp install claude-desktop # or: cursor, windsurf, claude-code datarunner mcp tools # what the agent can do with this key ``` - No key goes into the AI client's config: it points at the profile, which stays sealed. The profile is pinned by name, so a later auth use prod does not repoint the agent at production. - Read-only by default. Acknowledging alerts and testing connections are not even shown to the model without --allow-writes. - Every id is validated before it becomes a URL, queries are rate-limited per minute, and the instructions tell the model that database content is data, never instructions. > Free-form SQL takes the same path as the console editor: the server refuses destructive statements and applies column-masking policies before the result reaches the model. ## Output and exit codes The default format is a table. Pass --json or --csv when a program will read the output. Only then does progress go to standard error, so it cannot dirty what you are capturing. Nothing is guessed: PowerShell reports output as redirected even at an ordinary prompt, so trying to detect it printed JSON at people who just wanted to look. ``` datarunner query run 3f2a... | jq '.rows[0]' datarunner query run 3f2a... --format csv > revenue.csv ``` | Code | Means | | --- | --- | | 0 | ok | | 1 | a check you asked for failed (the tool worked) | | 2 | wrong usage | | 3 | credential missing or refused | | 4 | the server refused, or could not be reached | > The split between 1 and 4 is the point: a build has to tell “the data is wrong” from “the tool is broken” without parsing prose. ## Other commands - datarunner monitor status --fail-on-down: hold a deploy while something is already down. - datarunner query list, connection list, whoami. --- # Database monitor Source: https://www.datarunner.app/en/docs/monitors The health of every connected database: what is checked, the metrics that come with it, and how an incident starts. ## What is checked Each connection can have a monitor. It runs, on a clock, the same health test the connections screen uses. A new connection starts with its monitor on, every 5 minutes; you can switch it off when creating the connection or change the interval later. When the database answers, the monitor uses the same connection to read the engine’s own statistics: active sessions and their ceiling, idle transactions, blocked sessions, the oldest running query, cache hit ratio, database size and replication lag. What the engine does not report is left blank, never zero. ## Rules on the metrics On the connection screen, a rule states the limit that matters, for example “sessions above 80% of the ceiling for 5 minutes”. It only fires after the tolerance period and tells you again when things are back to normal. ## Interval and limits | Plan | Monitors | Minimum interval | | --- | --- | --- | | Solo | 1 | 5 minutes | | Pro | 5 | 2 minutes | | Team | 50 | 60 seconds | | Business | 500 | 15 seconds | ## From failure to incident A single failure does not open an incident. Networks hiccup, and an alert per hiccup trains everyone to ignore alerts. An incident opens when failures pass the threshold you set, and closes by itself when checks pass again. The recorded duration starts at the first failure, not at the moment the incident opened. The alert says what depends on the database: which reports read from it and how many recipients are waiting for the result. Those reports’ schedules can be held until the database is back. --- # Bridge to a private network Source: https://www.datarunner.app/en/docs/bridge How to query a database only your network can reach, without opening a firewall port. ## How it works The DataRunner agent runs on a machine inside your network and opens an outbound line to us itself. A connection marked “through the bridge” reaches its database over that line, so a database on 10.0.0.5 or behind a VPN becomes queryable with no inbound rule at all. ## Install 1. In the console, under Connections → Bridges, create a bridge. The key is shown once. 2. Install the agent on the machine and run the command the screen shows, with the key and the list of databases it may reach. 3. On the connection, pick the bridge. From then on queries, reports and the monitor go through it. ``` datarunner-agent bridge --server https://api.datarunner.app --key drb_… --allow 10.0.0.5:5432 --save ``` ## What the agent can and cannot do What the bridge can reach is decided by the allow-list, on your machine: a request for any other address is refused right there. The agent holds no database credential, exposes no port and accepts no remote command. The key is stored hashed on the server and can be rotated at any time. It keeps itself up to date: a few times a day it reads the manifest from the channel it was installed from, and when there is a newer version it downloads the binary from that version’s immutable directory, verifies the declared SHA-256, runs the binary once so it states its own version, and only then swaps it in. ## Platforms - Windows: x86-64 and ARM64 - Linux: x86-64 and ARM64 > There is no macOS build. When there is, it will appear on the download page. --- # Alerts and routes Source: https://www.datarunner.app/en/docs/alerting Where the notice of a database going down, or of a rule that fired, goes. ## Alert routes A route says which channel an alert goes out on, and in what order: email, Slack, Telegram, WhatsApp or webhook. It applies to database monitors, metric rules and report rules, and is defined once. A later step with a delay is escalation: if nobody acknowledges the alert within 10 minutes, the second channel is told. Every alert also reaches the console bell, route or not. > The routes screen has a simulator: it tells you whether an alert would match a route and whether each step would reach anyone, without waiting for a real outage. --- # Security and data Source: https://www.datarunner.app/en/docs/security Encryption, roles, authentication, audit, and what you can export or delete. ## Encryption - Connection credentials and channel configuration: AES-GCM at rest. - User passwords: bcrypt at work factor 12. Never in plaintext, never reversible. - Traffic: TLS between you and the service, and between the service and your database when the server offers it. ## Who gets in, and what they can do - Password, passkey, or social sign-in. - Roles with per-resource permissions; a workspace can adjust what each role reaches. - Scoped per-workspace API keys for automation and for the command line. The scope narrows on top of the role of whoever created the key, and a key never grants platform-wide powers. Available from Team up. - Sessions are visible and revocable one by one. ## Audit The audit log records who did what and when, and can be exported on a schedule to a workspace destination. Column policies let you mask sensitive fields in query results for roles that should not see them. > Masking matches on the source schema, table and column. The alias the query gave the field does not count. On Trino, Presto and Athena the protocol does not report which table each result column came from, so a policy on those sources is stored and never applied. The screen says so at the moment you create the policy; to mask for real on those sources, do it in the view or table itself. ## Export and delete - Export: download your personal data in a machine-readable format, straight from the console. - Deletion: the account enters a grace period before permanent removal, and you can cancel within it. - Retention: run data follows the plan’s retention and is deleted by a routine, not on request. > Security issues: write to projeto@datarunner.app. We acknowledge receipt and keep you posted until the fix ships. --- # Dashboards and sharing Source: https://www.datarunner.app/en/docs/dashboards Panels built from queries, per-dashboard filters, public links with password and expiry, and the iframe. ## What a dashboard is A dashboard is a grid of widgets, and each widget is a saved query drawn as a table, number, line, area, bar, pie, scatter, histogram, gauge, heatmap, combo, treemap or funnel. The query stays one thing: changing the SQL changes the widget on every dashboard that uses it. Plan limits: 2 dashboards on Solo, 10 on Pro, 25 on Team, 200 on Business. - Dashboard filters become query parameters (`:name`), so one date-range filter reaches every widget that declares it. - Results come from the query cache when there is one; "Refresh" forces a re-read from the database. - Column masking policies apply on a dashboard exactly as in the editor, and no path returns the raw value. ## Public link Any query, report or dashboard can get a public link: whoever has it sees the resource read-only, no account needed. Data is re-read on every visit, always with masking applied. 1. On the dashboard, choose Share and, optionally, set a password and an expiry date. 2. The link is shown once, because it is stored hashed and cannot be displayed again. Lost it? Settings → Shares issues a replacement without losing the view count. 3. "Copy embed code" gives the same link as an `