Quand vous interrogez SNOWFLAKE.ACCOUNT_USAGE.QUERY_HISTORY ou ACCESS_HISTORY, vous voyez exactement les 365 derniers jours. Pas un de plus. Cette rétention est codée en dur dans le share SNOWFLAKE que Snowflake maintient pour chaque compte. Elle n'est pas exposée en paramètre, elle ne se négocie pas avec votre Account Executive.
Pour une équipe Data qui gère Snowflake comme un entrepôt analytique classique, ce n'est pas bloquant. Pour une équipe qui doit prouver à un auditeur qui a accédé à telle table de données de santé il y a deux ans et demi, c'est un mur.
Le plafond à 365 jours n'est pas négociable
Rétention trop courte. 365 jours face aux 3 ans minimum attendus en audit RGPD et aux durées plus longues que demandent certains régulateurs sectoriels. Le référentiel ISO 27001 (contrôle A.12.4) n'impose pas un chiffre mais exige que les logs soient conservés "pendant une période appropriée" et protégés contre la modification. 365 jours, pour un auditeur, c'est rarement "approprié".
Coût compute masqué. Chaque requête sur ACCOUNT_USAGE consomme des credits du warehouse qui la porte. À petite échelle on ne le voit pas. Dès qu'on industrialise des dashboards FinOps ou des jobs de détection d'anomalies qui scannent QUERY_HISTORY toutes les heures, la ligne budgétaire devient visible.
Pas d'alerting natif. Les vues ACCOUNT_USAGE sont réactives. Pour détecter qu'un utilisateur a élevé ses privilèges il y a 20 minutes, il faut requêter la vue, comparer à un baseline, déclencher une alerte. Rien de cela n'existe dans Snowflake. Il faut une couche externe, ou un SIEM.
Logs silotés. Ces logs vivent dans Snowflake, interrogeables en SQL uniquement. Votre équipe cyber travaille sur Elastic, Splunk ou un SIEM managé. Elle ne va pas apprendre Snowflake pour corréler trois événements d'accès.
Verdict Rester dans
ACCOUNT_USAGEcomme seule source de vérité pour l'audit, c'est faire porter au Data Warehouse un rôle de système de record légal pour lequel il n'est pas conçu. L'externalisation des logs n'est pas une optimisation. C'est un chantier de compliance à part entière.
Ce qu'il faut exporter, dans quel ordre
Il y a une vingtaine de vues dans ACCOUNT_USAGE. Tout sortir est une erreur : coût de stockage inutile, complexité de maintenance, et surtout bruit qui noie le signal. Voici le tri qu'on applique chez nos clients.
Le socle P0 couvre 80 % des cas d'audit : qui s'est connecté, qui a requêté quoi, qui a lu quelle donnée sensible. C'est le triptyque qu'on met en production en premier. Le P1 vient immédiatement après parce que les auditeurs ISO 27001 demandent systématiquement la traçabilité des privilèges, et que la trace Cortex devient critique dès que vous ouvrez les fonctions IA natives de Snowflake aux équipes métier. Le P2 attend qu'un besoin FinOps concret arrive.
L'architecture qui tient
Le pattern qui marche en production : Snowflake pousse ses logs vers un bucket S3 immutable, via une Scheduled Task qui déclenche un COPY INTO sur un external stage. Le consommateur final, que ce soit un SIEM, Athena pour de l'audit interne ou un outil de FinOps, lit le S3. Snowflake ne sait pas qui consomme, et s'en moque.
Schéma · Flux d'export des logs Snowflake vers S3
Export poussé par Snowflake, supervisé par l'orchestrateur, consommé par N outils. Le bucket est l'unique point de contact.
Export depuis Snowflake. Le bon pattern : une Scheduled Task Snowflake déclenchée toutes les heures, qui exécute un COPY INTO @external_stage vers S3. L'external stage pointe sur le bucket avec un storage integration configuré (IAM role assumé par Snowflake). Le delta se fait via une table de watermark maintenue en interne, qui stocke le timestamp de la dernière exportation par vue. Ça évite les doublons, ça rend le job idempotent.
Coût côté Snowflake : zéro credit. La vue ACCOUNT_USAGE est lue par un warehouse, certes, mais on prend un XS qu'on dimensionne pour tenir une poignée de secondes par heure. Sur un mois, la dépense est inférieure au bruit statistique du dashboard de consommation.
Stockage immutable (WORM). Le bucket S3 est configuré en Object Lock mode Compliance. Même le compte root AWS ne peut plus supprimer un objet avant l'expiration de sa période de rétention. Ce n'est pas un gadget : c'est exactement ce que demande ISO 27001 A.12.4.2. Versioning activé, MFA delete sur la configuration du bucket, et CloudTrail qui trace qui lit quoi sur le bucket. Les logs des logs, oui.
Orchestration et supervision. La Task Snowflake peut tourner seule, mais on la supervise toujours depuis un orchestrateur externe (VTOM, Airflow, n8n selon la plateforme cliente). Trois alertes à cabler : échec d'export, lag dépassé, et volume anormalement bas (la Task a tourné mais n'a rien écrit, c'est souvent une panne silencieuse côté privilèges ou stage).
Les trois pièges que personne ne vous dit au kickoff
Piège 1 : le lag ACCOUNT_USAGE est structurel. Les vues ACCOUNT_USAGE sont latentes d'environ 45 minutes, avec des pics documentés jusqu'à 3 heures selon la charge. Si votre besoin est de la détection d'intrusion temps-réel, cette architecture ne vous la donnera pas. Il faut passer par les Event Tables Snowflake pour les flux les plus critiques, ou accepter que la fenêtre de détection soit de T+1h minimum. Le choix doit être explicite et arbitré avec l'équipe cyber. On ne découvre pas cette contrainte en phase de recette.
Piège 2 : le format de fichier dépend du consommateur. Parquet est le format par défaut côté Snowflake : natif, compressé, optimal pour S3 et Athena. Mais si votre SIEM ne sait lire que du JSON ligne par ligne ou du CSV, vous ajoutez une couche de transformation qui n'était pas au plan. Avant d'écrire une ligne de code, valider par écrit le format attendu par chaque consommateur. C'est une question de 15 minutes qui évite 3 semaines de rework.
Piège 3 : QUERY_TEXT contient du SQL brut, donc potentiellement des PII. Un développeur qui fait un WHERE email = 'jean.dupont@example.fr' vient d'écrire une donnée personnelle en clair dans QUERY_HISTORY. Cette donnée part dans le S3 et devient immutable via Object Lock. Il y a deux parades : masquer ou hasher le contenu de QUERY_TEXT à l'export (on perd en valeur d'audit), ou documenter explicitement auprès du DPO que les logs d'audit relèvent du motif légitime de compliance et ne sont pas concernés par le droit à l'effacement. La seconde parade tient juridiquement, mais elle doit être cadrée par écrit avant la mise en production.
À arbitrer avec le RSSI avant développement Durée de rétention cible (3 ans minimum, souvent 7 à 10 ans pour les secteurs régulés). Format de fichier accepté par le SIEM. Politique de hashing ou masquage de
QUERY_TEXT. Ownership de la clé KMS (équipe Data ou équipe Sécurité). Sans ces quatre décisions formalisées, ne pas démarrer l'implémentation.
Coût réel, dimensionnement réel
Pour un compte Snowflake de taille moyenne qui génère environ 10 millions de lignes de QUERY_HISTORY par mois :
Le coût global sur une année complète reste en dessous de 200 euros/mois pour la majorité des comptes Snowflake de taille moyenne. C'est l'argument le plus simple à porter en comité : pour l'équivalent d'un déjeuner par semaine, on se met en conformité, on sort des 365 jours, et on rend les logs exploitables par la chaîne cyber.
La règle qu'on applique chez nos clients
Externalisation des logs Snowflake, trois décisions prises dès le kickoff, dans cet ordre. Durée de rétention validée par le RSSI et le DPO. Format de fichier validé avec le consommateur final. Politique de QUERY_TEXT (clair, masqué, hashé) tranchée juridiquement. Ensuite, et seulement ensuite, on écrit la première ligne de code.
Les projets qui échouent sur ce chantier ne tombent jamais sur la technique. Ils tombent sur un auditeur qui demande au bout de 18 mois une durée de rétention différente, sur un SIEM qui ne sait pas lire le format choisi, ou sur un DPO qui découvre que les logs contiennent des PII non déclarés. Le socle technique tient en deux semaines. Le cadrage, c'est 80 % du succès.

