cloud-infra-data — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited cloud-infra-data (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
| Service | Best fit | Cost model |
|---|---|---|
| BigQuery | Variable/spiky workloads, serverless preference | Per-TB scanned (on-demand) or slot reservations |
| Snowflake | Multi-cloud, strong SQL, virtual warehouse isolation | Per-credit (compute time) |
| Redshift | AWS-native, predictable workloads, RA3 storage separation | Per-node/hour or serverless per-RPU |
| Databricks | Spark workloads, ML/data science teams | DBU per hour |
| Athena | Ad-hoc queries on S3, minimal ops | Per-TB scanned |
The biggest practical difference: BigQuery and Athena are serverless (no cluster to manage); Snowflake and Redshift require you to think about concurrency and warehouse sizing.
| Service | Use for |
|---|---|
| S3 (AWS) | Data lake, staging area, Parquet/Delta/Iceberg tables |
| GCS (GCP) | Same as S3 in the GCP ecosystem |
| ADLS Gen2 (Azure) | Azure data lake, hierarchical namespace for Hadoop compatibility |
All three are object stores — they look like key-value stores, not filesystems. The "folder" structure in the key name is just a naming convention.
s3://my-data-lake/
raw/
source=salesforce/
year=2024/month=01/day=15/
events_20240115_001.parquet
processed/
domain=churn/
year=2024/month=01/
churn_features_20240101.parquet
archive/
...Separate raw and processed data in the key hierarchy so you can apply different retention policies and IAM permissions to each layer.
Partition on the columns most commonly used in WHERE clauses. For time-series data, year/month/day is standard. Avoid over-partitioning — having millions of tiny files is worse than having a few large ones.
# PySpark — write with partitioning
df.write \
.partitionBy("year", "month", "day") \
.mode("overwrite") \
.parquet("s3://my-bucket/processed/events/")Partition column types matter: BigQuery and Athena push partition filters down efficiently. Use date/timestamp columns for time partitioning, not string representations — 2024-01-15 as a DATE, not "20240115" as a STRING.
| Format | Best for | Compression |
|---|---|---|
| Parquet | Columnar analytics, default choice | Snappy (fast), Zstd (small) |
| Delta Lake | ACID transactions, upserts, time travel | Parquet underneath |
| Iceberg | Multi-engine, large tables, schema evolution | Parquet underneath |
| ORC | Hive/EMR workloads | Zlib |
Target 128MB–1GB per file after compression. Files smaller than ~10MB create metadata overhead that slows queries on all columnar engines.
BigQuery on-demand charges per TB scanned. The biggest lever is how much data your queries touch.
-- Always filter on partition column to prune scans
SELECT user_id, event_type
FROM `project.dataset.events`
WHERE DATE(created_at) BETWEEN '2024-01-01' AND '2024-01-31' -- partition pruning
AND event_type = 'purchase';
-- Check bytes scanned before running expensive queries
-- In BigQuery UI: the validator shows estimated bytes in the top rightCluster your tables on the columns most used in WHERE and JOIN after the partition column — clustering reduces bytes scanned within a partition.
CREATE TABLE `project.dataset.events`
PARTITION BY DATE(created_at)
CLUSTER BY user_id, event_type
AS SELECT ...;On-demand is cheaper for infrequent/bursty workloads. Reservations (flat-rate pricing) make sense when you're spending > ~$2,000/month on on-demand, or when you need predictable query concurrency for dashboards.
Use the Storage Read API for fast data export to Pandas/Spark — much faster than exporting to CSV first.
from google.cloud import bigquery_storage
client = bigquery_storage.BigQueryReadClient()
# Reads directly into Arrow/Pandas without intermediate storageRA3 separates compute from storage — you pay for storage on S3 and scale compute independently. This is almost always the right choice for new Redshift clusters.
-- Distribute fact tables by the join key to minimize data movement
CREATE TABLE orders (
order_id BIGINT,
user_id BIGINT,
amount DECIMAL(10,2)
)
DISTSTYLE KEY DISTKEY (user_id) -- co-locate with users table
SORTKEY (created_at); -- skip scans on date range queriesMismatched distribution keys between joined tables cause expensive data redistribution across nodes. Check SVL_QUERY_SUMMARY for DS_DIST_BOTH steps — those are the expensive ones.
Query Parquet/ORC files directly on S3 without loading into Redshift:
CREATE EXTERNAL SCHEMA raw_lake
FROM DATA CATALOG DATABASE 'my_glue_db'
IAM_ROLE 'arn:aws:iam::123456:role/redshift-spectrum-role'
CREATE EXTERNAL DATABASE IF NOT EXISTS;
SELECT * FROM raw_lake.events WHERE event_date = '2024-01-15';Use Spectrum to query raw/archive data without paying for Redshift storage on cold data.
Each pipeline component should have only the permissions it needs, scoped to the specific resources it touches.
// S3 policy for a pipeline that reads raw and writes processed
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:ListBucket"],
"Resource": [
"arn:aws:s3:::my-bucket/raw/*",
"arn:aws:s3:::my-bucket"
]
},
{
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:DeleteObject"],
"Resource": "arn:aws:s3:::my-bucket/processed/*"
}
]
}When pipelines need to read from another team's account, use IAM roles + resource-based policies rather than sharing credentials.
// Bucket policy in Account A — allows Role in Account B to read
{
"Principal": {"AWS": "arn:aws:iam::ACCOUNT_B:role/pipeline-role"},
"Action": ["s3:GetObject"],
"Resource": "arn:aws:s3:::account-a-bucket/shared/*"
}# Create a service account per pipeline
gcloud iam service-accounts create churn-pipeline-sa
# Grant BigQuery read on the source dataset
gcloud projects add-iam-policy-binding my-project \
--member="serviceAccount:[email protected]" \
--role="roles/bigquery.dataViewer"
# Grant GCS write on the output bucket only
gsutil iam ch serviceAccount:[email protected]:objectCreator gs://my-output-bucket/| Pattern | Savings |
|---|---|
| Parquet + Snappy instead of CSV | 60–80% storage reduction; 5–10x less scanned in BigQuery/Athena |
| Partition pruning in all queries | Often 90%+ reduction in bytes scanned |
| S3 Intelligent-Tiering for archive data | 40–68% storage cost on cold data |
| Right-size Redshift/Snowflake warehouses | Pause warehouses when idle; use auto-suspend |
| Columnar projection — select only needed columns | Directly reduces scanned bytes in columnar engines |
| Compact small files before querying | Reduces metadata overhead and improves scan speed |
Before going to production:
s3:* or bigquery.admin for pipelines)~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.