En 2026, la stack ELT (Extract, Load, Transform) s’est imposée comme le standard de facto pour les pipelines de données. Fini les ETL monolithiques qui transforment avant de charger : aujourd’hui, on ingère d’abord les données brutes dans un entrepôt, puis on les transforme avec des outils modernes comme dbt. Dans ce guide complet, je vous montre comment assembler Airbyte (ingestion), dbt (transformation) et PostgreSQL (stockage) pour construire un pipeline data robuste, versionné et maintenable.

Pourquoi Airbyte + dbt + PostgreSQL ?

La combinaison de ces trois outils répond à un besoin précis : séparer l’ingestion de la transformation pour gagner en flexibilité et en maintenabilité.

  • Airbyte : connecteur open-source qui ingère des données depuis 300+ sources (APIs, bases de données, fichiers, SaaS) vers votre destination. En 2026, Airbyte Cloud gère le scaling automatiquement, et la version self-hosted a atteint une maturité remarquable.
  • dbt (data build tool) : outil de transformation qui applique la philosophie « software engineering » aux données : modèles SQL versionnés dans Git, tests automatisés, documentation générée, CI/CD natif.
  • PostgreSQL : base open-source robuste, capable de servir d’entrepôt analytique léger à moyen. Avec les extensions pg_partman, postgres_fdw et les index columnaires, il tient tête à des solutions bien plus coûteuses.

Le tout forme une stack 100% open-source, sans vendor lock-in, et opérable par une seule personne.

Architecture de la solution

Voici le schéma de notre pipeline :

┌─────────────┐     ┌──────────┐     ┌──────────────┐     ┌──────────────┐
│  Sources    │────▶│ Airbyte  │────▶│ PostgreSQL   │────▶│  dbt         │
│  (APIs, DB, │     │ (extract │     │ raw_data     │     │ (transform)  │
│   SaaS...)  │     │  + load) │     │ (schema RAW) │     │ analytics    │
└─────────────┘     └──────────┘     └──────────────┘     └──────────────┘
                                                                    │
                                                                    ▼
                                                           ┌──────────────┐
                                                           │  Metabase /  │
                                                           │  Superset    │
                                                           │  (visualise) │
                                                           └──────────────┘

Deux schémas PostgreSQL distincts :

  • raw_data : données brutes chargées par Airbyte (tables en l’état)
  • analytics : données transformées par dbt (tables, vues, modèles)

Étape 1 : Préparer PostgreSQL

Commencez par créer les utilisateurs et les schémas nécessaires. On crée un utilisateur dédié pour Airbyte (droits d’écriture) et un pour dbt (lecture raw + écriture analytics).

-- Utilisateur Airbyte : écriture dans raw_data
CREATE USER airbyte_user WITH PASSWORD 'mot_de_passe_securise';
CREATE SCHEMA IF NOT EXISTS raw_data AUTHORIZATION airbyte_user;
GRANT CREATE, USAGE ON SCHEMA raw_data TO airbyte_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA raw_data 
    GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO airbyte_user;

-- Utilisateur dbt : lecture raw_data + écriture analytics
CREATE USER dbt_user WITH PASSWORD 'autre_mot_de_passe';
CREATE SCHEMA IF NOT EXISTS analytics AUTHORIZATION dbt_user;
GRANT USAGE ON SCHEMA raw_data TO dbt_user;
GRANT SELECT ON ALL TABLES IN SCHEMA raw_data TO dbt_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA raw_data 
    GRANT SELECT ON TABLES TO dbt_user;
GRANT ALL ON SCHEMA analytics TO dbt_user;

Astuce : activez les index columnaires avec l’extension pg_columnstore si vous traitez des volumes supérieurs à 50 Go. Pour un usage modéré, des index B-tree classiques suffisent.

Étape 2 : Installer et configurer Airbyte

Airbyte peut être déployé en mode Cloud (géré) ou self-hosted via Docker. Pour ce guide, on utilise le déploiement Docker local :

# Cloner et lancer Airbyte
mkdir airbyte && cd airbyte
wget https://raw.githubusercontent.com/airbytehq/airbyte/main/run-ab-platform.sh
chmod +x run-ab-platform.sh
./run-ab-platform.sh -b

# Airbyte UI accessible sur http://localhost:8000

Une fois l’interface accessible, configurez votre source (par exemple une API Stripe, une base MySQL, ou un bucket S3) et votre destination PostgreSQL :

  • Host : localhost (ou l’IP de votre serveur PostgreSQL)
  • Port : 5432
  • Database : votre base
  • Default Schema : raw_data
  • User : airbyte_user
  • SSL : activé (obligatoire en production)

Créez ensuite une connexion entre la source et la destination. Choisissez le mode de réplication : Incremental | Append + Deduped est le plus efficace pour la plupart des cas, car il évite les doublons tout en ne rechargeant que les nouvelles données.

Étape 3 : Structurer le projet dbt

Installez dbt Core et l’adaptateur PostgreSQL :

pip install dbt-core dbt-postgres

# Initialiser le projet
dbt init my_analytics_project
cd my_analytics_project

Configurez le fichier ~/.dbt/profiles.yml pour connecter dbt à PostgreSQL :

my_analytics_project:
  target: dev
  outputs:
    dev:
      type: postgres
      host: localhost
      user: dbt_user
      password: autre_mot_de_passe
      port: 5432
      dbname: analytics_db
      schema: analytics
      threads: 4
      keepalives_idle: 0

Organisez votre projet dbt avec une structure claire :

my_analytics_project/
├── dbt_project.yml
├── models/
│   ├── staging/          # Modèles 1:1 des sources brutes
│   │   ├── sources.yml   # Déclaration des sources
│   │   └── stg_stripe__payments.sql
│   ├── intermediate/     # Transformations intermédiaires
│   │   └── int_payments__daily.sql
│   └── marts/            # Modèles finaux (utilisés par les dashboards)
│       ├── finance/
│       │   └── fct_revenue_monthly.sql
│       └── marketing/
│           └── fct_campaign_performance.sql
├── tests/                # Tests personnalisés
│   └── assert_revenue_positive.sql
└── macros/               # Fonctions SQL réutilisables
    └── cents_to_euros.sql

Étape 4 : Écrire les modèles dbt

Déclarez d’abord vos sources dans models/staging/sources.yml :

version: 2

sources:
  - name: raw_data
    database: analytics_db
    schema: raw_data
    tables:
      - name: stripe_payments
        description: "Paiements bruts importés par Airbyte depuis Stripe"
        columns:
          - name: id
            tests:
              - unique
              - not_null
          - name: amount
            description: "Montant en centimes"
            tests:
              - not_null
          - name: created
            tests:
              - not_null

Puis écrivez votre premier modèle staging :

-- models/staging/stg_stripe__payments.sql
{{ config(materialized='view') }}

SELECT
    id AS payment_id,
    amount / 100.0 AS amount_eur,
    status,
    created::timestamp AS payment_created_at,
    currency,
    customer_id
FROM {{ source('raw_data', 'stripe_payments') }}
WHERE status != 'canceled'

Et un modèle final dans les marts :

-- models/marts/finance/fct_revenue_monthly.sql
{{ config(materialized='table') }}

SELECT
    DATE_TRUNC('month', payment_created_at) AS revenue_month,
    COUNT(DISTINCT customer_id) AS unique_customers,
    COUNT(*) AS total_transactions,
    SUM(amount_eur) AS total_revenue_eur,
    AVG(amount_eur) AS avg_transaction_eur,
    SUM(SUM(amount_eur)) OVER (
        ORDER BY DATE_TRUNC('month', payment_created_at)
        ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
    ) AS cumulative_revenue_eur
FROM {{ ref('stg_stripe__payments') }}
GROUP BY 1
ORDER BY 1

Le mot-clé {{ ref() }} est crucial : il permet à dbt de résoudre automatiquement les dépendances entre modèles et d’exécuter le DAG dans le bon ordre.

Étape 5 : Tester et documenter

dbt intègre des tests natifs — utilisez-les sans modération :

# Exécuter tous les tests
dbt test

# Exécuter les tests d'un modèle spécifique
dbt test --select stg_stripe__payments

# Générer et servir la documentation
dbt docs generate
dbt docs serve  # Ouvrira http://localhost:8080

Ajoutez un test personnalisé pour valider la cohérence des données :

-- tests/assert_revenue_positive.sql
SELECT *
FROM {{ ref('fct_revenue_monthly') }}
WHERE total_revenue_eur < 0

Ce test échoue si une ligne de revenu mensuel est négative — ce qui indiquerait un problème dans les données source.

Étape 6 : Orchestrer le pipeline complet

L’orchestration relie Airbyte (chargement) et dbt (transformation). Trois approches en 2026 :

Option A : Airbyte + dbt intégré (simple)

Airbyte permet d’ajouter une étape de transformation dbt directement dans une connexion. Configurez :

  • Le dépôt Git contenant votre projet dbt
  • La commande dbt à exécuter : dbt build --select marts
  • L’image Docker dbt (ex : ghcr.io/dbt-labs/dbt-postgres:1.9.0)

Airbyte exécute dbt automatiquement après chaque sync réussie.

Option B : Apache Airflow (production)

from airflow import DAG
from airflow.providers.airbyte.operators.airbyte import AirbyteTriggerSyncOperator
from airflow.providers.dbt.cloud.operators.dbt import DbtCloudRunJobOperator
from datetime import datetime, timedelta

with DAG(
    dag_id='elt_stripe_to_analytics',
    start_date=datetime(2026, 1, 1),
    schedule_interval='0 6 * * *',  # Tous les jours à 6h
    catchup=False,
    default_args={'retries': 2, 'retry_delay': timedelta(minutes=5)}
) as dag:

    extract_load = AirbyteTriggerSyncOperator(
        task_id='airbyte_sync_stripe',
        airbyte_conn_id='airbyte_default',
        connection_id='stripe_to_postgres',
        asynchronous=False
    )

    transform = DbtCloudRunJobOperator(
        task_id='dbt_run_models',
        dbt_cloud_conn_id='dbt_cloud_default',
        job_id='12345',
        check_interval=30
    )

    extract_load >> transform

Option C : GitHub Actions (léger)

Pour les projets modestes, un cron GitHub Actions suffit :

# .github/workflows/elt-daily.yml
name: ELT Pipeline Quotidien
on:
  schedule:
    - cron: '0 6 * * *'
  workflow_dispatch:

jobs:
  elt:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Déclencher sync Airbyte
        run: |
          curl -X POST https://api.airbyte.com/v1/jobs \
            -H "Authorization: Bearer ${{ secrets.AIRBYTE_API_KEY }}" \
            -d '{"connectionId": "your-connection-id", "jobType": "sync"}'
      - name: Installer et exécuter dbt
        run: |
          pip install dbt-postgres
          dbt deps
          dbt build --target prod

Bonnes pratiques pour la production

1. Gestion des schémas évolutifs

Airbyte détecte automatiquement les changements de schéma. Configurez le paramètre schema_change_handling pour éviter les ruptures de pipeline quand une colonne est ajoutée ou renommée côté source.

2. Tests de données systématiques

Ajoutez des tests dbt sur chaque colonne critique : not_null, unique, accepted_values, et des tests de relation (relationships) pour valider les clés étrangères. Un pipeline sans tests est un pipeline qui vous trahira au pire moment.

3. Monitoring et alertes

Branchez les logs dbt et Airbyte sur votre stack de monitoring (Grafana, Datadog, ou même un simple webhook Slack). En 2026, la data observability (qualité, fraîcheur, lignage des données) est devenue aussi critique que le monitoring applicatif.

4. Incrémentation et CDC

Pour les gros volumes, privilégiez le Change Data Capture (CDC) via les slots de réplication PostgreSQL plutôt que les syncs full-refresh. Airbyte gère le CDC nativement et dbt peut être configuré en mode incremental :

{{ config(
    materialized='incremental',
    unique_key='payment_id',
    on_schema_change='sync_all_columns'
) }}

SELECT * FROM {{ ref('stg_stripe__payments') }}
{% if is_incremental() %}
WHERE payment_created_at > (SELECT MAX(payment_created_at) FROM {{ this }})
{% endif %}

Coût et scalabilité

Avec cette stack auto-hébergée :

  • Airbyte : gratuit (open-source), besoin d’un serveur 4 vCPU / 8 Go RAM (~30 €/mois chez OVH ou Hetzner)
  • PostgreSQL : gratuit, montez en gamme si besoin (8 Go RAM pour 50-100 Go de données)
  • dbt Core : gratuit (la version Cloud avec scheduler intégré démarre à 100 $/mois si vous ne voulez pas gérer Airflow)

Coût total : moins de 50 €/mois pour un pipeline traitant plusieurs millions de lignes par jour. Le même service chez Fivetran + dbt Cloud + Snowflake coûterait 10 à 30 fois plus.

Conclusion

En 2026, construire un pipeline ELT professionnel n’a jamais été aussi accessible. La combinaison Airbyte + dbt + PostgreSQL offre le meilleur rapport qualité/prix du marché : flexibilité, maintenabilité, et un contrôle total sur votre stack de données, sans les coûts prohibitifs des solutions SaaS.

Le plus important n’est pas l’outil, mais la discipline : versionnez vos transformations, testez vos données, documentez votre logique métier. C’est ce qui distingue un pipeline jetable d’un pipeline industrialisé.


Sources et références

W
WP Admin Lab

Architecte web full-stack. WordPress, performance, data et sécurité. Notes de terrain, tests reproductibles et retours d'expérience.