A production-grade credit union data warehouse deployed on Azure — built around the four data systems every institution runs, unified with dbt, and surfaced as live executive dashboards with campaign targeting. Modeled on a ~$1B portfolio. Architecture scales to any cloud.
Every credit union runs the same categories of system — core banking, consumer lending, mortgage servicing, and originations. The vendors differ. The problem doesn't.
The CFO's delinquency report is pulled manually every Monday. The CLO can't see approval rates by DTI band without querying the origination platform. The CRO doesn't know which branch has the highest charge-off concentration. The CMO can't see product penetration without a data request.
When every answer requires a different login, the answer to every question is "let me check."
We connect all four system categories into a single warehouse — on whatever cloud you run, with whatever source systems you have. We built a star schema with dbt, automated data quality tests, and surfaced five executive dashboards calibrated for each audience.
Portfolio balance, delinquency rate, and charge-off rate are always current. The CLO sees DTI distribution by channel. The CRO has a roll rate matrix. The CMO sees product penetration by member type. Marketing gets campaign-ready target lists — auto refi opportunities, cross-sell candidates, and early-stage delinquency outreach — all driven by the same warehouse.
A specialist team handles the work end to end: data engineering builds the pipeline, a QA analyst runs the test suite, and a security reviewer audits credentials, encryption, and access before anything goes live. The dbt models are cloud-portable by design — this POC runs on Azure SQL today and deploys to Snowflake, Databricks, or Fabric with a one-line profile change.
This POC is live on Azure today — Azure SQL Database for the warehouse, Azure Blob Storage as the CSV landing zone, Azure Data Factory for automated ingestion, and Metabase on Azure Container Instances for dashboards. Total cost: ~$1.50/day on a free trial. The same dbt models deploy to Fabric, Snowflake, or Databricks with a one-line profile change.
This POC runs live on Azure SQL with Metabase dashboards and ADF pipelines. In production we deploy on whatever cloud and tooling your institution already runs.
The difference between a generic consultant and someone who has built this before shows up in the details — data model patterns, regulatory context, the reports your board actually asks for. Here's what that looks like in practice.
validFrom, validTo, and a current-row flag. Resolving to current state must happen before any downstream join.
balance_date is what makes the delinquency trend chart work.
| Layer | This POC | Production equivalent | Why the pattern holds either way |
|---|---|---|---|
| Warehouse | Azure SQL (Basic) | Snowflake · Databricks · Fabric · Synapse | Cheapest Azure option at ~$5/mo proves the model works. Same dbt project runs against any warehouse with a one-line profile change — no model rewrites. |
| Transform | dbt-sqlserver | dbt Cloud · dbt Core on any warehouse | Lineage graph, automated tests, and version-controlled models — the signal a credit union CTO needs to see regardless of the underlying engine. |
| Ingestion | Azure Data Factory | ADF · Glue · Fivetran · Airbyte | ForEach pipeline loads 23 CSVs from Blob Storage — parameterized datasets, no per-table pipeline duplication. Same pattern scales to hundreds of source files. |
| Semi-structured parsing | regexp_extract() | PARSE_XML() · PARSE_JSON() · Spark schema inference | Consumer lending platforms export blobs. Parsing in the staging layer — not the source — keeps raw data immutable and the transform logic auditable. |
| BI layer | Metabase on ACI | Power BI · Tableau · Sigma · Superset | Dashboards sit on top of mart models — changing the BI tool never touches the warehouse. The mart layer is the contract. |
| Campaign analytics | 3 mart models | CRM integration · marketing automation | Auto refi, cross-sell, and delinquency outreach targets built as dbt models — no separate tool needed. The warehouse becomes a revenue driver, not just a reporting tool. |
| SCD2 resolution | isCurrentRow filter | Same pattern — column names vary by platform | Resolve to current state in int_member_current before any downstream join. Doing it at query time with a subselect causes fanout; doing it in a CTE costs one materialization. |