As of Postgres 12 (Oct. 2019) CTEs are no longer materialized by default and are eligible for predicate push down.
The planner may still struggle but it’s not true that a CTE is an optimization fence.
https://www.depesz.com/2019/02/19/waiting-for-postgresql-12-...