# Replicating Lazy (Late-Binding) Views in PostgreSQL Using dbt Custom Materialization — Safe for Production?

**URL:** https://discourse.getdbt.com/t/replicating-lazy-late-binding-views-in-postgresql-using-dbt-custom-materialization-safe-for-production/19222
**Category:** In-Depth Discussions
**Tags:** materialization, best-practice, postgres
**Created:** [April 30, 2025, 4:00pm UTC](https://discourse.getdbt.com/t/replicating-lazy-late-binding-views-in-postgresql-using-dbt-custom-materialization-safe-for-production/19222 "2025-04-30T16:00:15Z")
**Posts on this page:** 1
**Page:** 1

<div class="post-metadata">

### Author: ![kemaltulum](https://sea2.discourse-cdn.com/flex020/user_avatar/discourse.getdbt.com/kemaltulum/32/3604_2.png) [@kemaltulum](https://discourse.getdbt.com/u/kemaltulum)
#### Post date: [April 30, 2025, 4:00pm UTC](https://discourse.getdbt.com/t/replicating-lazy-late-binding-views-in-postgresql-using-dbt-custom-materialization-safe-for-production/19222/1 "2025-04-30T16:00:15Z")

</div>

Hi all,

I’m trying to replicate **lazy (late-binding) view behavior** in PostgreSQL using a custom dbt materialization — mainly to avoid tight coupling between views and underlying tables, like what’s possible in Snowflake or Redshift with `WITH NO SCHEMA BINDING`.

### 🎯 What I’m Doing

The materialization does the following:

1. Executes the model SQL with `LIMIT 0` to introspect the columns and types.
2. Creates a **PostgreSQL function** like this:

```auto
create function my_model__func()
returns table (<col defs>) as $
begin
  return query
  <model_sql>;
end;
$ language plpgsql;

```

1. Then creates a **view with the model name** that wraps the function:

```auto
create view my_model as
select * from my_model__func();

```

This lets me treat it like a normal view in downstream models or BI tools, but keeps the logic **deferred until query time**. The view and function remain in place even if source tables are dropped — errors only happen at runtime when the view is queried.

### ❓ What I’d Like Feedback On

So far this is working well in practice — but before adopting it more broadly, I’d love your thoughts:

- **Is this a solid pattern to use in production** , especially under moderate-to-heavy query load?
- Are there any **known downsides** (e.g., performance, caching, planner behavior) to wrapping views around `RETURNS TABLE` functions?
- Would you recommend any **improvements** to this approach — or are there better ways to achieve “late binding” behavior in PostgreSQL?
- Any experience from others who have tried similar techniques?

Thanks in advance — I’d really appreciate any thoughts or cautions.
