---
title: "Quickstart: a self-refreshing dashboard"
description: Connect a warehouse, publish a dashboard against it, arm a schedule, and watch a real run land in the history.
updated: 2026-09-11
tier: pro
---

This walkthrough ends somewhere specific: a run appearing in your dashboard's
refresh history that nobody triggered. That is the product working. Everything
before it is setup.

**Before you start:** the [first quickstart](/start/quickstart) done, a plan
that is paid or trialing (your first workspace's 14-day Pro trial counts), and
credentials you can read with for a warehouse a refreshing dashboard can publish
against. Step 1 below names that set and how to check it, because it is read out
of the database as each publish is judged rather than fixed here.

## What you need from your warehouse

You will type these into the Dashies web app, not into your AI tool. Credentials
never pass through the AI or the publish service.

Give Dashies a **read-only login**. It only ever runs `SELECT`, and a read-only
role means a mistake in a query cannot become a mistake in your warehouse. On
SQL Server a read-only login is required rather than merely advisable.

:::steps

1. **Connect the warehouse.**

   In the Dashies web app, open **Data sources** and add a connection for your
   engine. The form asks for the connection details and for which tables,
   schemas, or datasets Dashies may read. Only what you allowlist there is
   readable.

   Which engines a refreshing warehouse dashboard can publish against is read out
   of the database as each publish is judged, so the refusal names the current set
   and this sentence names a reading: **on 2026-09-18 it was BigQuery,
   Databricks, Oracle Database, Postgres, SQL Server and Snowflake**. Redshift
   connects, explores and validates, but a publish against it is refused. Believe
   the refusal over this date.

   Test the connection before leaving the page. A connection has to be **active**
   before anything can be authored against it.

   If you belong to more than one workspace, create the connection **from inside
   the workspace the dashboard will live in**. A connection belongs permanently
   to the workspace it was created in. See
   [Connections and scope](/concepts/connections-and-scope) before you pick.

2. **Ask your AI for the dashboard.**

   Name the connection and the numbers. For example:

   > Build me a Dashies dashboard from my Snowflake connection showing revenue
   > and order count by month and by plan for the last 12 months. Refresh daily.

   Your AI reads the schema, designs the grain, writes one `SELECT` per dataset,
   validates it against the connection, dry-runs the whole spec, and publishes.

3. **Read the publish report.**

   Four things in it are worth your attention, and three of them are easy to skip
   past:

   | In the report | What it is telling you |
   |---|---|
   | Dashboard URL | where the dashboard lives |
   | Datasets | the mode each dataset resolved to, and why |
   | `warnings` | non-blocking advisories; read them, they are usually right |
   | `obligations` | a cross-check the server cannot do for you |

   An **obligation** appears when a dataset reads more than one row source: a
   join, a CTE, a comma join, or a derived table. It is not a finding and not an
   error. It is the server saying that no static check can tell whether that join
   duplicated rows, so you have to. Do the check in step 5.

4. **Arm the schedule.**

   If you asked for a cadence in step 2, it is already set. To change it, open
   **Schedules** in the web app and pick a cadence and a time in your own
   timezone.

   The cadence is a coarse choice (`manual`, `hourly`, `daily`, `weekly`,
   `monthly`) plus an optional interval and anchor: "every 6 hours", or "daily at
   `09:00` America/New_York". [Schedules](/concepts/schedules) covers the
   combinations that are allowed and the ones that are refused.

5. **Cross-check one number before you share the link.**

   Take one additive measure, sum it across the whole dashboard, and compare
   against a direct aggregate over the base table run in your own SQL client:

   ```sql
   select sum(amount) as revenue
   from orders
   where ordered_at >= current_date - interval '12 months'
   ```

   If the dashboard total is larger, a join has fanned out and every figure on
   the page is inflated by the same mechanism.
   [Measure correctness](/concepts/measure-correctness) is the page that explains
   why this check has no substitute.

:::

## Check it worked

The dashboard being live is not the thing to check. **A run landing that you did
not ask for** is the thing to check.

1. **Open Schedules in the web app.** Your dashboard should be listed with its
   cadence and a **Next refresh** time. If the cadence reads "On demand", the
   schedule was never armed and no run will ever happen.

2. **Wait for the next slot, then open the History tab.** A new row should
   appear with a status, a row count, and a duration. That row is the proof:
   nothing you did caused it.

   A run can legitimately be a little late. Dashies schedules to the minute you
   pick and starts the run within about half an hour of it, so a dashboard ten
   minutes past its nominal time is healthy rather than broken.

3. **Expect "No change" sometimes.** A successful run whose numbers came back
   byte-identical is marked as no change. That is a healthy state and it is
   labelled precisely so you can tell it apart from a stall.

4. **Do not check the dashboard's "Edited" timestamp.** A refresh deliberately
   does not move it. Edited and Refreshed are two different clocks: Edited means
   the last time a person changed the dashboard, Refreshed lives on the Schedules
   page. A dashboard refreshing perfectly can show an "Edited" date from weeks
   ago.

:::warning{title="If no run appears at all"}
Check the cadence first, then the plan. A schedule armed while paid keeps its
cadence after a plan lapses, and each due run is then recorded as a skip rather
than a failure, so nothing looks broken and nothing updates. On a workspace
warehouse dashboard the plan that is checked is the plan of whoever **created the
data source**, which is why a whole team's dashboards can stop at once. See
[Plans and what is gated](/concepts/plans-and-gating).
:::

## Next

You now have the full loop. The pages that will save you the most time from here:

- [Datasets and the four modes](/concepts/dataset-modes), when a filter you want
  does not work or a dashboard is refused for being too large.
- [Measure correctness](/concepts/measure-correctness), when a number looks
  wrong.
- [Connections and scope](/concepts/connections-and-scope), when a dashboard
  publishes but never refreshes.
