Stop Recomputing Your Dashboard on Every Page Load.

A dashboard that runs a heavy aggregation against live tables works fine in a demo and then crawls in production, because every single page load recalculates the same numbers from scratch. The usual fix is piping everything into a dedicated warehouse like Snowflake purely so the dashboard has something fast to read.
For a huge share of “internal dashboard” use cases, a materialized view does the same job with zero new infrastructure.
Pre-bake the aggregation
CREATE MATERIALIZED VIEW daily_revenue AS
SELECT date_trunc('day', created_at) AS day, sum(total) AS revenue
FROM orders
GROUP BY 1;
CREATE UNIQUE INDEX ON daily_revenue (day);That unique index is not optional decoration — I confirmed this directly by dropping it and trying to refresh: Postgres refuses outright with cannot refresh materialized view "daily_revenue" concurrently, and tells you exactly why. It's the single most common way this recipe trips people up, so build the index in from the start.
Refresh without locking out readers
REFRESH MATERIALIZED VIEW CONCURRENTLY daily_revenue;CONCURRENTLY recalculates in the background and hot-swaps only the changed rows into place — anyone reading the view mid-refresh sees the old data until the swap completes, never a lock, never a blank dashboard.
SELECT * FROM daily_revenue ORDER BY day DESC LIMIT 30;Your dashboard just reads this like any other table. No ETL pipeline, no separate job runner — the “transform” step is the view definition.
Put it on a schedule with zero extra infrastructure
If you have pg_cron available:
SELECT cron.schedule('refresh-daily-revenue', '*/15 * * * *',
'REFRESH MATERIALIZED VIEW CONCURRENTLY daily_revenue');Scheduled refresh, running inside the database you already have.
Why this beats a dedicated warehouse for most dashboards
- ▹No ETL pipeline to babysit — the transform step is a SQL view.
- ▹Dashboards stay fast as data grows, since they're reading pre-computed numbers, not raw transaction history.
- ▹You control the refresh cadence directly — hourly, nightly, or on demand, it's one command either way.
Where Snowflake still wins
Ad-hoc analytical queries across terabytes of historical data, joining many large fact tables in ways your operational schema was never modeled for. If your “warehouse” need is really “make this one dashboard fast,” you may not need one.
Field Manual Series · Every recipe tested
This is one of eight infrastructure swaps.
Just Use Postgres is a 24-page field manual on replacing MongoDB, Redis, Elasticsearch, Pinecone, and more with the database you're probably already running. Every recipe in it — including this one — was run against a live Postgres instance before it went in the book.
Pay a warehouse to pre-compute two numbers, or run one REFRESH. Your call.
Up next in the series
“Find What's Nearby” Doesn't Need a Separate GIS Stack
See the full series →