← All postsData

Scheduled SQL Queries: Run SQL Against Your Databases on a Schedule

Almost every application accrues a set of SQL jobs that need to run on a clock. A nightly revenue rollup. An hourly sync that flattens a few tables into one your dashboard can read cheaply. A reconciliation query that checks yesterday's ledger. Individually they are a dozen lines of SQL. Collectively they are the reason teams stand up an orchestrator.

And the orchestrator is almost always heavier than the work. You reach for a managed Airflow, a dbt Cloud job, or a small always-on box running cron — and now your data is being pulled out of your database, into a separate service, to be processed, and written back. For a Canadian team with a data-residency clause, that separate service is often the exact thing you were trying to avoid: a US-hosted SaaS with a copy of your rows.

As of this week, Canner does this natively. Write SQL, set a schedule, and it runs against your own databases — in Montreal, with nothing pulled out.

SQL plus a schedule — that's the whole thing

A scheduled query is exactly two inputs: the SQL and a cron schedule. There is no pipeline to define, no destination table to pre-declare, no connection string to paste. You write the statement you would run by hand, and Canner runs it for you on the schedule you set, keeping a full run history.

It is the SQL sibling of scheduled jobs, which fire an HTTP POST at a webhook in your app. Reach for a scheduled job when the work lives in your application code; reach for a scheduled query when the work is SQL.

Reference your databases by name

A scheduled query can reach any project database your account owns. You name it in the SQL — project.schema.table. That is the entire connection step (a hyphen in a slug becomes an underscore: my-shop my_shop). And because you can name more than one, a single statement can bridge across projects you own:

-- Roll up yesterday's orders into a reporting table,
-- written straight into the project's own Postgres.
CREATE OR REPLACE TABLE shop.public.daily_sales AS
SELECT date_trunc('day', created_at) AS day,
       count(*)                      AS orders,
       sum(amount)                   AS revenue
FROM shop.public.orders
WHERE created_at >= now() - interval '1 day'
GROUP BY 1;

Nothing is materialised for you — the SQL decides where results go. Qualify a table with a project and it lands in that project's real Postgres database, immediately readable by your app. A plain SELECT that writes nothing is still valid; its result is logged as a small preview and then discarded, exactly like a query at a psql prompt.

A cross-project example — join two databases you own and append to a third:

INSERT INTO warehouse.public.customer_orders
SELECT o.id, o.amount, c.segment
FROM shop.public.orders o
JOIN crm.public.customers c ON c.id = o.customer_id
WHERE o.created_at >= now() - interval '1 day';

Isolated by construction

Running arbitrary SQL on a schedule only works if each run is boxed in. Every run executes in its own in-memory engine with a memory cap and a timeout, and with local filesystem access disabled — a query reaches your Postgres databases over the network, but a read_csv or COPY … TO aimed at a host file returns a clean permission error. A run can only see databases your own account owns; another tenant's data is never in scope. A runaway aggregation OOMs inside its own cgroup, never on the host.

You manage the rest from the dashboard: Run now to test without waiting, Pause and resume, a cancel button on a run that is still going, and a run history that marks each run Succeeded, Failed, Timeout, or Cancelled.

The sovereignty part

The reason this matters beyond convenience: the entire loop stays in Canada. Your data never leaves your account to be processed. There is no external orchestrator holding credentials to your database, no US-hosted job runner with a copy of your rows, no egress bill for moving data to an analytics cloud and back. The query runs a few milliseconds from the database it reads, on infrastructure that is Canadian-owned and Montreal-hosted — the same posture as Data Workshop and the rest of the platform.

Scheduled queries are available on every plan, Starter included. Open Compute → Scheduled queries to write your first one, or read the full guide.

About the author

Colin Shand is the founder of Canner, a Canadian deployment platform operated from Quebec. He writes about sovereign infrastructure, the Canadian startup ecosystem, and building independently.

Try Canner.

Drop a project, get a live URL on Canadian infrastructure in about 30 seconds. Free tier available.