scenic-views/scenic · error · Scenic::Adapters::Postgres::ConcurrentRefreshesNotSupportedError
Concurrent materialized view refreshes require Postgres 9.4
Error message
Concurrent materialized view refreshes require Postgres 9.4 or newer
What it means
REFRESH MATERIALIZED VIEW CONCURRENTLY shipped in Postgres 9.4, one release after materialized views themselves. Scenic's Postgres adapter raises Scenic::Adapters::Postgres::ConcurrentRefreshesNotSupportedError inside refresh_materialized_view when concurrently: true is requested and connection.supports_concurrent_refreshes? is false, meaning the connected server reports postgresql_version below 90400. A 9.3 server therefore passes the materialized-view gate and fails only when a concurrent refresh is requested; the check runs before the REFRESH statement is sent.
Source
Thrown at lib/scenic/adapters/postgres.rb:290
# @api private
def connection
Connection.new(connectable.connection)
end
private
attr_reader :connectable
delegate :execute, :quote_table_name, to: :connection
def raise_unless_materialized_views_supported
unless connection.supports_materialized_views?
raise MaterializedViewsNotSupportedError
end
end
def raise_unless_concurrent_refresh_supported
unless connection.supports_concurrent_refreshes?
raise ConcurrentRefreshesNotSupportedError
end
end
def refresh_dependencies_for(name, concurrently: false)
Scenic::Adapters::Postgres::RefreshDependencies.call(
name,
self,
connection,
concurrently: concurrently
)
end
end
end
end
View on GitHub (pinned to f2162dbddb)
Solutions
- Drop the flag: Scenic.database.refresh_materialized_view(:posts) issues a plain REFRESH MATERIALIZED VIEW, which 9.3 supports
- Gate concurrency on server capability: pass concurrently: ActiveRecord::Base.connection.postgresql_version >= 90400
- Upgrade the server to Postgres 9.4 or newer so non-blocking concurrent refreshes work
Example fix
# before (raises on Postgres 9.3) Scenic.database.refresh_materialized_view(:posts, concurrently: true) # after: capability-gated concurrently = ActiveRecord::Base.connection.postgresql_version >= 90400 Scenic.database.refresh_materialized_view(:posts, concurrently: concurrently)
Defensive patterns
Strategy: validation
Validate before calling
concurrently = ActiveRecord::Base.connection.postgresql_version >= 90400 Scenic.database.refresh_materialized_view(:posts, concurrently: concurrently)
Type guard
def concurrent_refresh_supported? ActiveRecord::Base.connection.postgresql_version >= 90400 end
Try / catch
begin Scenic.database.refresh_materialized_view(:posts, concurrently: true) rescue Scenic::Adapters::Postgres::ConcurrentRefreshesNotSupportedError Scenic.database.refresh_materialized_view(:posts) # retry without CONCURRENTLY end
Prevention
- Standardize every environment on Postgres 9.4+ when concurrent refreshes are used
- Gate the concurrently flag on postgresql_version instead of hard-coding true
- Remember REFRESH ... CONCURRENTLY also requires a unique index covering all view rows, even on 9.4+
When it happens
Trigger: Scenic.database.refresh_materialized_view(:posts, concurrently: true) on a Postgres 9.3 server; the same call with cascade: true, where RefreshDependencies may refresh dependent materialized views concurrently; scheduled refresh jobs or background code hard-coding concurrently: true and deployed against an environment still on 9.3.
Common situations: Legacy production on 9.3 while development machines run 9.4+; a background refresh job written against a newer server than staging provides; mixed database fleets where only some hosts have been upgraded.
Related errors
- Materialized views require Postgres 9.3 or newer
- Cannot replace materialized views
- a transaction is required to perform a side-by-side update
- #{method} is reversible only if given a revert_to_version
- version is required
AI-assisted analysis of scenic-views/scenic@f2162dbddb (2026-08-23).
Data as JSON: /api/errors/ea68401094c6ff80.
Report an issue: GitHub.