Materialized View
matureSummary
Pre-compute and persist the result of an expensive query as a physical table or document, serving subsequent reads from the pre-computed result rather than re-executing the query on every request.
Problem
Complex queries (aggregates, multi-table JOINs, full-text search over large datasets) take seconds to execute against normalised source tables and cannot be served at the latency required for interactive user interfaces or real-time dashboards.
Description
A materialised view is a stored query result. Instead of executing a complex JOIN, aggregation, or analytical query at read time, the query is executed once (or periodically) and its result is stored in a physical table or document. Subsequent reads query the materialised result directly, typically reducing read latency from seconds to milliseconds.
PostgreSQL supports native materialised views with REFRESH MATERIALIZED VIEW [CONCURRENTLY]. Non-concurrent refresh acquires an exclusive lock for the entire duration of the refresh: blocking all reads on the view until the refresh completes. CONCURRENTLY builds the new result in a temporary structure and swaps it in, allowing reads throughout, but requires a unique index and takes significantly longer. Refresh is manual unless triggered by a scheduled job, cron, or application event.
For higher refresh frequency or event-driven invalidation, application-managed materialised views in Redis or a denormalised document store are common. The application explicitly rebuilds the view when upstream data changes, using a background worker triggered by database events (CDC), Kafka events, or a post-write hook.
ClickHouse supports materialised views that update incrementally as new data arrives : on each INSERT, the materialised view query runs over only the new rows and merges the result into the view table. This is efficient for streaming aggregation but limited to aggregations that are composable (sum, count, max) rather than exact (median, percentile).
The key operational characteristic is staleness: any materialised view is always behind the source data by the refresh interval. For dashboards and reporting, 1–5 minute staleness is often acceptable. For product UI showing counts or summaries, the refresh schedule must be chosen based on user expectations, not technical convenience.
Tradeoffs
Pre-computed result eliminates query execution at read time; latency drops from seconds to milliseconds
Concurrent readers share one refresh; read QPS to source tables drops dramatically
Always behind source data by at least one refresh cycle; must be explicitly managed
Non-concurrent PostgreSQL refresh blocks all reads on the view for its full duration
Requires additional storage for the pre-computed result
Refresh scheduling, monitoring staleness, and handling failed refreshes add ops overhead
When to use
Query is expensive to compute (>100ms) and the underlying data changes infrequently
If data changes every minute but the query takes 5 seconds, refreshing on every change is impractical; materialising the result is the right tradeoff
The same expensive query is executed by many concurrent users
Materialising the result once serves all concurrent readers from the same pre-computed snapshot; database load scales with refresh frequency, not user count
Exact real-time accuracy is not required: bounded staleness is acceptable
Refresh cycles introduce a staleness window; if users need exact current data, a real-time aggregation pipeline or a direct query is needed instead
Query result can be refreshed in a time window that satisfies staleness requirements
A refresh that takes 5 minutes cannot maintain 1-minute staleness SLA; refresh time constrains achievable freshness
When not to use
Data changes at the same rate it is read (high write rate with low read multiplier)
Frequent refreshes under high write load may consume more resources than simply executing the query on demand
Query results are highly personalised per user
A materialised view is a shared snapshot; it cannot serve per-user personalised data without one view per user (impractical at scale)
Exact real-time consistency is required
Materialised views are always stale by definition; use a streaming aggregation pipeline for near-real-time requirements
Operational Requirements
Use REFRESH MATERIALIZED VIEW CONCURRENTLY for views serving live traffic
Non-concurrent refresh locks the view exclusively; on a 100M-row view this can take minutes and makes the view completely unavailable during that time
Monitor view staleness and alert if refresh falls behind schedule
A failed or delayed refresh means the view is older than the SLA commitment; users consuming stale data will not notice unless staleness is surfaced
Test refresh duration on production-size data before setting refresh schedule
Refresh duration on staging data may be 10x faster than production; measure on production-volume data to set a realistic schedule
Build index on materialised view columns used in WHERE and ORDER BY
An unindexed materialised view still requires a full scan on each read; the view only provides the pre-computation benefit, not query plan benefit
Characteristics
Technologies
Canonical
Alternatives
Relationships
Evolves from
Evolves to
Complements
Basis
Native database feature with well-understood refresh semantics; lock and staleness tradeoffs are clearly defined and operationally documented
Related Architecture Knowledge
Outbound: this entity affects
Materialized views pre-join and pre-aggregate related data into a single denormalized read table, eliminating the N+1 query pattern by ensuring that reads of the materialized view require no additional per-row follow-up queries.
Tradeoffs
- ·Materialized views are stale between refreshes: acceptable for most read paths, unacceptable for financial reads
- ·Refresh adds write amplification proportional to the view's JOIN complexity
- ·Very large materialized views can themselves become query bottlenecks if they are not properly indexed
Inbound: affects this entity
Analytics-heavy workloads pre-compute expensive aggregations and joins into materialized views, reducing repeated full-scan query cost from minutes per query to milliseconds per lookup.
Tradeoffs
- ·Materialized views add write overhead (refresh cost) and storage overhead (duplicate data)
- ·Stale materialized views silently serve stale data: requires monitoring of last_refresh timestamp
- ·Complex views with many dependencies make refresh ordering complex
CQRS separates the write model (normalized, ACID) from the read model; materialized views implement the read model by pre-computing the denormalized view that the query side serves. Each pattern makes the other more operationally tractable.
Tradeoffs
- ·Eventual consistency between write model and materialized views is inherent to the pattern
- ·Multiple views add storage and refresh overhead: each view is a separately maintained copy of data
- ·Debugging requires understanding which view version a query returned: important for support workflows
Fan-out on read for high-follower accounts can be accelerated by maintaining a materialized view of each account's recent posts, reducing the per-follower fetch to a single indexed lookup per followed account.
Full relationship →Materialized views provide fast read access to pre-aggregated data; time series rollup applies tiered aggregation over time, feeding the materialized view at each resolution level.
Full relationship →Trino can query Iceberg and Delta Lake materialized views defined over object storage, enabling low-latency analytics against pre-aggregated data without a separate data warehouse.
Full relationship →Used In Architecture Scenarios
AI / RAG Application
A Retrieval-Augmented Generation (RAG) architecture that combines vector similarity search for semantic document retrieval with relational metadata filtering, using PostgreSQL with pgvector as the unified store for both embeddings and structured data. Redis provides a semantic cache to avoid redundant embedding model inference and reduce vector index query load for repeated or similar queries. Kafka manages the asynchronous embedding generation pipeline that keeps the vector index current as source documents are added or updated.
Analytics Pipeline
An OLAP-oriented analytics architecture that ingests operational changes from PostgreSQL via WAL-based CDC into Kafka, then routes them to a columnar analytics store (ClickHouse or Snowflake) for product analytics, business intelligence, and operational reporting. The CQRS separation ensures analytical queries never degrade transactional write performance, and materialized views provide pre-aggregated query acceleration for the most expensive analytical patterns.
Read-Heavy Application
A CMS for publishing and serving structured content: articles, documentation, product pages, and localized variants: where read APIs serve 50–100x more traffic than editorial write APIs. PostgreSQL stores the content graph (articles, authors, categories, taxonomy) and workflow state (draft, in-review, scheduled, published). Redis caches published content objects for read APIs. Elasticsearch powers full-text content search with faceting and relevance ranking. Cache invalidation on publish must be fast and complete; N+1 query patterns on content relationship traversal are the dominant database performance risk during reads.
AI / RAG Application
A low-latency feature serving platform for ML model inference, providing both batch (offline) and real-time (online) feature access with strict training-serving consistency. Redis serves the hot feature cache with p99 latency targets below 5ms for online inference requests; PostgreSQL provides point-in-time feature lookups for offline training jobs with temporal consistency guarantees; Cassandra stores high-cardinality feature entities at write scale beyond PostgreSQL's single-primary ceiling; Kafka streams feature computation events from online feature pipelines to update the cache; Qdrant stores vector features for embedding-based model inputs and similarity lookups; ClickHouse serves feature analytics and drift monitoring across training dataset populations. Feature versioning is first-class: every feature value is tagged with a pipeline_version and computed_at timestamp to support model reproducibility and training-serving skew diagnosis.
Analytics Pipeline
A metrics, logs, and traces ingestion and query platform built to absorb the telemetry output of a production system fleet: including the telemetry volume spikes that accompany the incidents the platform is meant to detect. ClickHouse stores metrics data with automatic time-based rollup via continuous materialized views; TimescaleDB provides complementary time-series storage for high-cardinality alert evaluation; Kafka buffers the ingestion stream against downstream write pressure, decoupling ingest acceptance rate from storage write throughput; Elasticsearch serves log full-text search and structured field filtering; Redis caches dashboard query results and active alert state for sub-100ms alert evaluation latency. The alert engine evaluates threshold and anomaly rules against pre-computed materialized views, not raw data, to bound alert evaluation cost independent of ingestion volume.
Search-Heavy Application
A content platform architecture centered on Elasticsearch for full-text search, faceted navigation, and ranked results, with PostgreSQL as the transactional source of truth and Redis for session management and hot content caching. WAL-based CDC maintains index freshness by streaming PostgreSQL changes into Elasticsearch asynchronously. The core tension is between search index freshness, query performance, and index maintenance cost under high write volume.