Mastering dbt Core with PostgreSQL: From Fragmented SQL to Standardized Data Workflows

Database tutorial - IT technology blog
Database tutorial - IT technology blog

The Nightmare of “Manual SQL”

Have you ever found yourself “swimming” through 50 long SQL files—some on your local machine, others floating on a server? Every time the revenue calculation logic changes, you have to hunt through every file, manually run each command, and pray you didn’t copy-paste into the wrong place.

After years of working with PostgreSQL and MongoDB, I realized that managing data transformation logic with pure scripts is a maintenance mistake. dbt (data build tool) was born to solve this problem. It brings a software engineering mindset to the world of Data Analysts with: Version Control (Git), Testing, and Automated Documentation.

In the ELT (Extract – Load – Transform) model, dbt handles the T. Once raw data is settled in PostgreSQL, dbt shapes it into clean data tables, ready for dashboarding.

Installing dbt Core and Connecting to PostgreSQL

To get started, your machine needs Python installed (version 3.8 or higher is recommended). dbt Core is completely free and runs via the command line (CLI), making it extremely lightweight.

1. Installing the dbt-postgres library

Don’t just install the generic dbt package. Install the specific adapter for PostgreSQL to achieve the best performance:

pip install dbt-postgres

Then, type dbt --version. If the version information appears, you’re on the right track.

2. Initializing the Project

Open your terminal in your workspace and run:

dbt init my_first_dbt_project

dbt will ask you for parameters like host, port, and user. If you’re unsure, just press Enter; we’ll configure the details in the next step.

Configuring Secure Connections via profiles.yml

By default, dbt stores connection information in ~/.dbt/profiles.yml rather than within the project directory. This approach ensures maximum security. You’ll never have to worry about accidentally pushing database passwords to GitHub.

Below is a standard configuration for a local environment:

my_first_dbt_project:
  outputs:
    dev:
      type: postgres
      threads: 4 # Number of models running in parallel
      host: localhost
      port: 5432
      user: postgres_user
      pass: your_password
      dbname: analytics_db
      schema: dbt_transformation
  target: dev

Pro tip: Separate the raw schema (raw data) and the analytics schema (processed data). This separation makes access control easy: Data Analysts only need read permissions for the analytics schema.

Writing Your First Model: Turning SELECT into a Table

In the dbt world, every .sql file is a Model. You don’t need to write tedious CREATE TABLE or DROP VIEW statements. Just write a SELECT statement, and dbt handles the heavy lifting.

For example, to calculate total customer spending, create the file models/marts/customer_orders.sql:

with orders as (
    select * from {{ source('raw', 'orders') }}
),

final as (
    select
        customer_id,
        count(order_id) as total_orders,
        sum(amount) as total_spent
    from orders
    group by 1
)

select * from final

The {{ source(...) }} function is the key. It helps dbt build a dependency graph (Lineage). If Table A needs data from Table B, dbt automatically runs Table B first without any manual intervention.

To execute, you only need to run one command: dbt run.

Data Quality Testing

Worried about duplicate data or Null values in ID columns? Instead of writing manual check scripts, declare them in the schema.yml file. dbt will automate this validation.

version: 2

models:
  - name: customer_orders
    columns:
      - name: customer_id
        tests:
          - unique
          - not_null
      - name: status
        tests:
          - accepted_values:
              values: ['placed', 'shipped', 'completed', 'returned']

When you run dbt test, the system scans the entire database. If it detects a row that violates a rule, dbt alerts you immediately. This ensures the reports you send to your boss are always 100% accurate.

Automating Documentation

Every Analyst’s fear is working with an “unknown” database without column descriptions. dbt solves this completely by automatically generating a professional documentation website.

Just two commands:

dbt docs generate
dbt docs serve

A web interface will appear, showing the entire table structure and the Lineage Graph. This is a visual diagram showing where data flows from and to. When a colleague asks about the logic, you just need to send them a link.

Operations and Monitoring

As the system grows to hundreds of models, manual commands are no longer efficient. You should integrate dbt into scheduling tools like Airflow or GitHub Actions.

With every run, dbt outputs JSON files in the target/ directory. You can leverage run_results.json to push logs into Grafana. This helps you track execution time and detect errors promptly before users report them.

Final advice: Don’t rush to migrate all your old SQL to dbt in a single day. Start with the most important tables and set up a few basic tests. You’ll see a noticeable difference in data control within just 1-2 weeks of implementation.

Share: