Data flow & failure modes
How a dealer stock file or Redbook feed physically gets from S3 into a Snowflake raw table, and where it can go wrong along the way.
Stock ingestion path
Two Lambdas, two very different jobs — see AWS resources for why the router only makes a routing decision and the processor does the actual work.
The Redbook path is the same shape but CSV-based and hand-rolled per feed — 5 separate Snowpipes (vehicles, makes, families, legacy map, cipher key), fed from a redbook-bronze bucket that a copyRedBookToBronzeBucket Lambda populates weekly from the manifold-<env> bucket.
Where this path can lose or duplicate data
Every Snowpipe COPY statement sets ON_ERROR = 'SKIP_FILE'.
- One malformed row or type mismatch skips the entire file, not just the bad row.
- There's no Terraform-managed alert on pipe or
COPYfailures — the only Snowflake-side alerting watchesTASK_HISTORYfor downstream dbt tasks, notPIPE_USAGE_HISTORY/COPY_HISTORY. - A skipped file surfaces only if someone notices missing rows. It doesn't page anyone.
The reverse (export) path is provisioned but not consumed.
- dbt writes gzip CSV exports to an S3 export bucket via a dedicated storage integration and stage (
snowflake-export-s3module). - The Lambda that was meant to consume those exports (
stockOutboundProcess, S3 export bucket → MySQL upsert) is fully commented out inserverless.yml. - Nothing currently reads what dbt writes there.
The trust-policy patch between an IAM role and its Snowflake storage integration runs via local-exec + AWS CLI, not declaratively.
- Snowflake generates the storage integration's
storage_aws_iam_user_arn/external ID only after the integration exists, so the IAM role's trust policy can't be set at creation time through the provider alone. - Both the Snowpipe and export-S3 modules work around this with a
null_resourcethat shells out toaws iam update-assume-role-policyusingvar.aws_profile. - This makes
terraform applynon-idempotent in the strict sense:terraform plancan't show the real state of the trust policy, and CI needs working AWS CLI credentials for the exact profile string, not just the Terraform provider credentials. - If that CLI call fails mid-apply, the storage integration and IAM role exist but the trust relationship is stale — Snowpipe silently can't assume the role to read S3, and nothing detects that condition automatically.
Cross-IaC coupling on the same path
Terraform doesn't own the Lambda functions in this path — they're deployed separately by the Serverless Framework app (platform/serverless/serverless.yml). Terraform does a data "aws_lambda_function" lookup on the deployed function, then creates the aws_lambda_permission and aws_s3_bucket_notification that wire S3 events to it.
This means terraform apply for this bucket notification depends on the Lambda already being deployed — an implicit ordering requirement between two separate deploy pipelines, not something Terraform enforces or documents itself.