Les données en retard sont la principale raison pour laquelle les modèles incrémentaux dérivent de la vérité source. Un enregistrement avec un timestamp du 20 mars arrive le 24 mars. Le modèle incrémental a déjà traité les données du 20 mars trois jours plus tôt. Sans gestion, cet enregistrement tardif est manqué définitivement et l’écart entre le modèle et la source se creuse à chaque exécution.
Les événements GA4, les conversions des plateformes publicitaires et les pipelines CDC présentent tous des arrivées tardives. Le pattern de fenêtre de lookback est l’approche standard.
Le pattern
Au lieu de traiter uniquement les données plus récentes que le dernier enregistrement de votre table, vous soustrayez une fenêtre fixe et retraitez une période glissante de données récentes :
{% set lookback_days = var('lookback_days', 3) %}
{{ config( materialized='incremental', unique_key='event_id', incremental_strategy='merge') }}
SELECT event_id, event_timestamp, user_id, event_typeFROM {{ ref('base__analytics__events') }}{% if is_incremental() %}WHERE event_timestamp >= ( SELECT DATEADD(DAY, -{{ lookback_days }}, MAX(event_timestamp)) FROM {{ this }}){% endif %}Chaque exécution retraite les 3 derniers jours de données, capturant les enregistrements arrivés tardivement dans cette fenêtre. La unique_key garantit que les enregistrements déjà présents dans la cible sont mis à jour plutôt que dupliqués (en supposant l’utilisation d’une stratégie merge ou delete+insert).
L’utilisation de var() avec une valeur par défaut rend le lookback configurable pour les backfills ad-hoc :
dbt run --select my_model --vars '{"lookback_days": 10}'Cela permet d’étendre la fenêtre après des problèmes de pipeline connus sans modifier le code du modèle.
Choisir la taille de la fenêtre
La bonne taille de fenêtre dépend du profil de latence de vos données — le temps que les enregistrements mettent à arriver après leur timestamp d’événement. Cela varie énormément selon le système source.
| Fenêtre | Couverture | Impact sur les coûts |
|---|---|---|
| 1 jour | Minimale ; manque la plupart des données tardives | Le plus bas |
| 3 jours | Bon équilibre ; couvre 99%+ des arrivées tardives typiques | Modéré |
| 7 jours | Capture presque toutes les données tardives | Plus élevé |
| 14+ jours | Couverture maximale | Significatif |
Trois jours est une valeur par défaut courante pour les modèles basés sur des événements et couvre la majorité des arrivées tardives dans des systèmes comme GA4, les plateformes publicitaires et les pipelines CDC typiques. Mesurer la distribution réelle de la latence — quel pourcentage d’enregistrements arrivent le jour même versus dans les 3 jours versus dans la semaine — détermine la fenêtre appropriée pour une source spécifique.
Le compromis sur les coûts est réel. Une fenêtre de lookback de 3 jours signifie que vous retraitez 3 jours de données source à chaque exécution au lieu des seuls nouveaux enregistrements. Sur une table qui traite 100 Go par jour, c’est 300 Go scannés par exécution. Sur BigQuery avec la tarification à la demande, c’est la différence entre 1,25 $ et 3,75 $ par exécution. À grande échelle ou à haute fréquence, cela s’accumule.
Lookback + prédicats incrémentaux
Si vous utilisez la stratégie merge sur une grande table, la fenêtre de lookback filtre côté source mais le merge scanne toujours la table de destination entière pour trouver des correspondances. Vous avez besoin de prédicats incrémentaux pour limiter également le scan de destination :
{% set lookback_days = 3 %}
{{ config( materialized='incremental', unique_key='event_id', incremental_strategy='merge', incremental_predicates=[ "DBT_INTERNAL_DEST.event_date >= DATE_SUB(CURRENT_DATE(), INTERVAL " ~ lookback_days ~ " DAY)" ]) }}
SELECT *FROM {{ ref('base__events') }}{% if is_incremental() %}WHERE event_date >= ( SELECT DATE_SUB(MAX(event_date), INTERVAL {{ lookback_days }} DAY) FROM {{ this }}){% endif %}La fenêtre du prédicat doit être au moins aussi large que la fenêtre de lookback. Des prédicats de destination plus étroits peuvent amener le merge à rater des correspondances légitimes.
Lookback avec insert_overwrite
Sur BigQuery, la stratégie insert_overwrite remplace des partitions entières. Vous pouvez utiliser une liste de partitions statique comme forme de lookback :
{% set partitions_to_replace = [ 'CURRENT_DATE()', 'DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY)', 'DATE_SUB(CURRENT_DATE(), INTERVAL 2 DAY)'] %}
{{ config( materialized='incremental', incremental_strategy='insert_overwrite', partition_by={'field': 'event_date', 'data_type': 'date'}, partitions=partitions_to_replace) }}Cela remplace les 3 derniers jours de partitions à chaque exécution. C’est souvent plus rentable que le merge avec un lookback car il n’y a pas de comparaison ligne par ligne — la partition entière est remplacée.
La limitation fondamentale
Les fenêtres de lookback ne capturent pas les enregistrements arrivant après la fermeture de la fenêtre. Un enregistrement de janvier arrivant en mars ne sera pas capturé par un lookback de 3 jours ou même de 14 jours.
Ce n’est pas un bug — c’est un compromis inhérent. Rendre la fenêtre suffisamment grande pour capturer toute arrivée tardive possible signifierait retraiter tellement de données que l’avantage de performance du traitement incrémental serait perdu.
La solution est en couches :
- Fenêtre de lookback gère les arrivées tardives routinières (couvre 95-99% des cas)
- Full refreshes périodiques réinitialisent la dérive accumulée (hebdomadaires ou mensuels, selon votre tolérance)
- Full refresh à la demande après des pannes de pipeline connues ou des problèmes de système source
Pour les très grandes tables où le full refresh est coûteux ou lent, planifiez les full refreshes pendant les heures creuses ou les weekends. Certaines équipes exécutent un incrémental quotidien et un full refresh hebdomadaire. D’autres exécutent un incrémental horaire et un full refresh mensuel. La cadence appropriée dépend de votre profil de latence des données et de votre tolérance à la dérive.
Surveiller la dérive
Vous pouvez mesurer la dérive en comparant les résultats incrémentaux à une baseline de full refresh sur un échantillon de données. Si votre modèle incrémental et un full refresh de la même fenêtre temporelle produisent des nombres de lignes ou des agrégats différents, vous avez une dérive.
Les tests unitaires dbt peuvent valider que votre logique de lookback est correcte pour des patterns d’arrivée tardive connus. Testez avec des enregistrements qui arrivent à la limite de votre fenêtre de lookback pour vous assurer qu’ils sont capturés.
Le changement de perspective clé : les modèles incrémentaux ne sont pas garantis d’être parfaitement cohérents avec la source. Ils sont une optimisation qui échange un peu de cohérence pour des coûts nettement inférieurs et des temps d’exécution plus rapides. La fenêtre de lookback et le full refresh périodique sont la façon dont vous maintenez ce compromis acceptable.