{"record":{"id":"ea68401094c6ff80","repo":"scenic-views/scenic","slug":"concurrent-materialized-view-refreshes-require-pos","errorCode":null,"errorMessage":"Concurrent materialized view refreshes require Postgres 9.4 or newer","messagePattern":"Concurrent materialized view refreshes require Postgres 9\\.4 or newer","errorType":"exception","errorClass":"Scenic::Adapters::Postgres::ConcurrentRefreshesNotSupportedError","httpStatus":null,"severity":"error","filePath":"lib/scenic/adapters/postgres.rb","lineNumber":290,"sourceCode":"      # @api private\n      def connection\n        Connection.new(connectable.connection)\n      end\n\n      private\n\n      attr_reader :connectable\n      delegate :execute, :quote_table_name, to: :connection\n\n      def raise_unless_materialized_views_supported\n        unless connection.supports_materialized_views?\n          raise MaterializedViewsNotSupportedError\n        end\n      end\n\n      def raise_unless_concurrent_refresh_supported\n        unless connection.supports_concurrent_refreshes?\n          raise ConcurrentRefreshesNotSupportedError\n        end\n      end\n\n      def refresh_dependencies_for(name, concurrently: false)\n        Scenic::Adapters::Postgres::RefreshDependencies.call(\n          name,\n          self,\n          connection,\n          concurrently: concurrently\n        )\n      end\n    end\n  end\nend\n","sourceCodeStart":272,"sourceCodeEnd":305,"githubUrl":"https://github.com/scenic-views/scenic/blob/f2162dbddb0fb0eb5d4b04d640dcec5303a387e8/lib/scenic/adapters/postgres.rb#L272-L305","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before (raises on Postgres 9.3)\nScenic.database.refresh_materialized_view(:posts, concurrently: true)\n\n# after: capability-gated\nconcurrently = ActiveRecord::Base.connection.postgresql_version >= 90400\nScenic.database.refresh_materialized_view(:posts, concurrently: concurrently)","handlingStrategy":"validation","validationCode":"concurrently = ActiveRecord::Base.connection.postgresql_version >= 90400\nScenic.database.refresh_materialized_view(:posts, concurrently: concurrently)","typeGuard":"def concurrent_refresh_supported?\n  ActiveRecord::Base.connection.postgresql_version >= 90400\nend","tryCatchPattern":"begin\n  Scenic.database.refresh_materialized_view(:posts, concurrently: true)\nrescue Scenic::Adapters::Postgres::ConcurrentRefreshesNotSupportedError\n  Scenic.database.refresh_materialized_view(:posts) # retry without CONCURRENTLY\nend","preventionTips":["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+"],"tags":["postgres","database-version","materialized-view","concurrent-refresh","scenic"],"backgroundTag":"database-version-unsupported","analyzedSha":"f2162dbddb0fb0eb5d4b04d640dcec5303a387e8","analyzedAt":"2026-08-23T09:20:35.041Z","schemaVersion":2},"datasetVersion":"2026-08-23T13:39:53.451Z"}