Retour au blog
BigQuery

Anatomie d'une facture BigQuery à 50k€/mois

Décomposition détaillée d'une facture BigQuery typique d'une scale-up. Où part l'argent, qui consomme quoi, et où se cachent les optimisations.

15 février 202615 min de lecture

Anatomie d'une facture BigQuery à 50k€/mois

Je vois régulièrement des factures BigQuery de scale-ups en croissance. Le pattern est souvent le même : une facture qui a explosé sans que personne ne comprenne vraiment pourquoi.

Dans 90% des cas que j'audite, la facture a triplé en moins d'un an — et l'équipe data découvre le problème quand le CFO débarque avec des questions.

Dans cet article, je décompose une facture typique de 50k€/mois pour montrer où part l'argent — et où se cachent les optimisations.


Le profil type

Imaginons une scale-up e-commerce classique :

  • Taille : 200 employés, 50 utilisateurs BigQuery actifs (dont 8 dans l'équipe data core)
  • Data team : 2 Data Engineers, 4 Analysts, 2 Data Scientists — le reste : Product, Finance, Marketing avec accès Looker
  • Volume : 2 TB de nouvelles données par jour
  • Stack : BigQuery + dbt + Looker
  • Historique : 3 ans de données, ~500 TB total

La facture mensuelle vient de passer de 15k€ à 50k€ en 8 mois. Personne ne sait exactement pourquoi.

J'ai vu chez un client cette exact situation : le Data Lead était persuadé que c'était le volume de données qui avait explosé. En réalité, 60% de l'augmentation venait d'un seul dashboard Looker mal configuré, rafraîchi toutes les 15 minutes par 30 utilisateurs.


Décomposition de la facture

Vue d'ensemble

TOTAL MENSUEL : 52 340€

├── BigQuery Analysis (Queries)    35 200€   67%
│   ├── On-demand queries          28 000€
│   └── BI Engine                   7 200€
│
├── BigQuery Storage               8 500€    16%
│   ├── Active storage             6 200€
│   └── Long-term storage          2 300€
│
├── Dataflow                       4 800€     9%
│
├── Cloud Storage (GCS)            2 400€     5%
│
└── Autres (Pub/Sub, etc.)         1 440€     3%

Premier constat : 67% des coûts viennent des requêtes. C'est là qu'il faut creuser.

À noter sur BI Engine : Ces 7 200€ correspondent à une réservation de 100 Go de mémoire BI Engine (~$0.0416/Go/heure × 730h × 100 Go). BI Engine accélère les requêtes Looker en gardant les données en mémoire. Le problème : beaucoup d'équipes activent BI Engine "pour la performance" sans vérifier si leurs dashboards en bénéficient vraiment. Dans ce cas, seuls 3 dashboards sur 25 utilisaient effectivement le cache BI Engine.


Analyse du compute (35k€)

Qui consomme ?

-- Top 10 des consommateurs (30 derniers jours)
-- Prix EUR : $6.25/TiB × 0.92 EUR/USD ≈ €5.75/TiB
SELECT
  user_email,
  COUNT(*) as query_count,
  SUM(total_bytes_billed) / POW(1024, 4) AS tb_scanned,
  ROUND(SUM(total_bytes_billed) / POW(1024, 4) * 5.75, 2) AS cost_eur
FROM `region-eu`.INFORMATION_SCHEMA.JOBS
WHERE creation_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)
  AND job_type = 'QUERY'
GROUP BY user_email
ORDER BY cost_eur DESC
LIMIT 10;

Résultat typique :

UtilisateurRequêtesTB scannésCoût
scheduler@projet.iam45 0002 10012 075€
looker@projet.iam128 0001 4508 337€
analyst-marie@3 2008905 117€
analyst-paul@2 8006203 565€
dbt-prod@1 2004802 760€

Insights :

  • Le scheduler (Airflow/dbt) représente 35% des coûts → pipelines à auditer
  • Looker fait 128k requêtes → beaucoup de cache miss, dashboards mal optimisés
  • 2 analysts consomment autant que le reste de l'équipe → requêtes exploratoires non optimisées

Quelles requêtes coûtent le plus ?

-- Top 20 requêtes les plus chères
SELECT
  job_id,
  user_email,
  ROUND(total_bytes_billed / POW(1024, 4) * 5.75, 2) AS cost_eur,
  ROUND(total_bytes_billed / POW(1024, 3), 1) AS gb_scanned,
  SUBSTR(query, 1, 200) AS query_preview
FROM `region-eu`.INFORMATION_SCHEMA.JOBS
WHERE creation_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
  AND job_type = 'QUERY'
ORDER BY total_bytes_billed DESC
LIMIT 20;

Patterns récurrents :

  1. SELECT * sur tables non partitionnées — Une requête, 2 TB scannés, 12€
  2. Dashboards sans filtre date — Chaque refresh scanne tout l'historique
  3. JOINs mal ordonnés — Explosion combinatoire
  4. Requêtes récurrentes identiques — Même requête 50x/jour sans cache

Opinion tranchée : Je déconseille fortement le mode on-demand au-delà de 10k€/mois de consommation. À ce stade, passez aux BigQuery Editions (Standard ou Enterprise). Le on-demand, c'est confortable mais c'est un chèque en blanc — et j'ai vu trop d'équipes se faire surprendre par une facture x3 après un incident de pipeline ou un stagiaire un peu trop curieux.


Analyse du storage (8.5k€)

Répartition active vs long-term

Problèmes typiques :

DatasetActiveLong-termProblème
raw_events180 TB20 TBPas de lifecycle
staging45 TB0 TBTables temporaires jamais supprimées
snapshots80 TB10 TBSnapshots gardés indéfiniment

Le ratio Active/Long-term devrait être ~30/70, ici c'est l'inverse.

La dernière fois que j'ai vu ce pattern, le client payait 3 000€/mois pour des tables de staging créées par un ancien employé parti depuis 18 mois. Personne n'osait les supprimer "au cas où".


Les 6 quick wins

1. Activer require_partition_filter (économie : ~8k€/mois)

ALTER TABLE `project.dataset.events`
SET OPTIONS (require_partition_filter = TRUE);

Ce que les gens comprennent mal : beaucoup pensent que le partitioning suffit. Non. Sans require_partition_filter, vos utilisateurs peuvent toujours scanner la table entière — ils le feront par paresse ou par erreur. Forcez la contrainte, sinon elle n'existe pas.

2. Réparer les dashboards Looker (économie : ~4k€/mois)

  • Filtres date obligatoires
  • Materialized Views pour agrégations communes
  • BI Engine sur tables fréquentes

3. Optimiser les pipelines dbt (économie : ~3k€/mois)

# dbt_project.yml
models:
  +partition_by:
    field: event_date
    data_type: date
  +cluster_by: ["country", "event_type"]

4. Nettoyer le staging (économie : ~1.5k€/mois)

ALTER TABLE `project.staging.temp_table`
SET OPTIONS (expiration_timestamp = TIMESTAMP_ADD(CURRENT_TIMESTAMP(), INTERVAL 7 DAY));

5. Lifecycle policy sur raw_events (économie : ~2k€/mois)

ALTER TABLE `project.raw.events`
SET OPTIONS (partition_expiration_days = 730);

6. Former les équipes (économie : ~3k€/mois)

  • Pas de SELECT *
  • Toujours filtrer sur la partition
  • Dry run avant exécution

Plan d'action

SemaineActionÉconomie estimée
1Partition filters8 000€
2Top 5 dashboards4 000€
3Pipelines dbt3 000€
4Cleanup + lifecycle3 500€
5Formation équipe3 000€

Total : ~21 500€/mois = 41% de réduction


Conclusion

Une facture BigQuery à 50k€, c'est rarement une fatalité. 30-50% peuvent être économisés avec :

  1. Forcer les bonnes pratiques (partition filters)
  2. Optimiser les gros consommateurs (dashboards, pipelines)
  3. Nettoyer le storage (lifecycle, tables zombies)
  4. Former les équipes (culture cost-aware)

Le plus dur n'est pas technique — c'est de maintenir ces pratiques dans le temps. J'ai vu des équipes faire le ménage une fois, économiser 40%, puis retomber au même niveau 6 mois plus tard parce que personne ne surveillait.

Si ce type de contenu t'aide, tu peux me suivre sur LinkedIn ou t'inscrire à la newsletter pour recevoir les prochains articles.

Jonathan Kini

Jonathan Kini

J'aide les équipes data à réduire et maîtriser leurs coûts BigQuery et Snowflake, sans sacrifier la performance. De la startup aux environnements data à grande échelle.