<figure class="wp-block-image aligncenter"><img src="https://flowgenius.in/wp-content/uploads/2026/01/storage-cost-optimization-execution-history.png" alt="Step by Step Guide to solve storage cost optimization execution history" /> <figcaption style="text-align: center;">Step by Step Guide to solve storage cost optimization execution history</p>
<hr />
</figcaption></figure>
<p style="margin-bottom: 2em; line-height: 1.9;"><strong>Who this is for:</strong> Ops engineers, DevOps leads, or SREs managing server‑less workflows (Step Functions, Durable Functions, Cloud Run jobs, etc.) who see execution‑history storage driving up their monthly bill. <strong>We cover this in detail in the </strong><a href="https://flowgenius.in/n8n-cost-optimization-at-scale/">n8n Cost, Scaling & Infrastructure Economics Guide.</a></p>
<hr style="margin: 55px 0; border: none; border-top: 1px solid #eee;" />
<h2 style="margin-bottom: 45px; line-height: 1.3;">Quick diagnosis</h2>
<p style="margin-bottom: 2em; line-height: 1.9;">Server‑less workflows automatically write execution‑history records to a log service (CloudWatch Logs, Azure Log Analytics, GCP Logging). If storage costs climb, the usual suspects are:</p>
<ul style="margin-bottom: 1.8em; line-height: 1.9;">
<li><strong>Retention</strong> longer than required.</li>
<li><strong>Uncompressed</strong> logs staying in a hot tier.</li>
<li><strong>No archiving</strong> strategy for older data.</li>
</ul>
<p style="margin-bottom: 2em; line-height: 1.9;">Pulling those three levers usually cuts storage spend by <strong>40 %–80 %</strong>, and you still keep auditability.<br />
<em>In production, the creep shows up after the first billing cycle.</em></p>
<hr style="margin: 55px 0; border: none; border-top: 1px solid #eee;" />
<h2 style="margin-bottom: 45px; line-height: 1.3;">1. Where execution history lives?</h2>
<p>If you encounter any <a href="/n8n-architecture-regulated-environments">n8n architecture regulated environments </a>resolve them before continuing with the setup.</p>
<table style="border-collapse: collapse; width: 100%; margin-bottom: 2em;">
<thead>
<tr>
<th style="border: 1px solid #ddd; padding: 13px;">Platform</th>
<th style="border: 1px solid #ddd; padding: 13px;">Default store</th>
<th style="border: 1px solid #ddd; padding: 13px;">Typical size per execution</th>
<th style="border: 1px solid #ddd; padding: 13px;">Default retention</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;"><strong>AWS Step Functions</strong></td>
<td style="border: 1px solid #ddd; padding: 13px;">CloudWatch Logs (<code>/aws/vendedlogs/states/<state‑machine‑name></code>)</td>
<td style="border: 1px solid #ddd; padding: 13px;">0.5 KB – 5 KB</td>
<td style="border: 1px solid #ddd; padding: 13px;">∞ (no auto‑expire)</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;"><strong>Azure Durable Functions</strong></td>
<td style="border: 1px solid #ddd; padding: 13px;">Log Analytics workspace (or Application Insights)</td>
<td style="border: 1px solid #ddd; padding: 13px;">1 KB – 10 KB</td>
<td style="border: 1px solid #ddd; padding: 13px;">30 days (configurable)</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;"><strong>Google Cloud Workflows</strong></td>
<td style="border: 1px solid #ddd; padding: 13px;">Cloud Logging (log bucket)</td>
<td style="border: 1px solid #ddd; padding: 13px;">0.3 KB – 4 KB</td>
<td style="border: 1px solid #ddd; padding: 13px;">30 days (default)</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;"><strong>AWS Lambda (invocation logs)</strong></td>
<td style="border: 1px solid #ddd; padding: 13px;">CloudWatch Logs (<code>/aws/lambda/<function></code>)</td>
<td style="border: 1px solid #ddd; padding: 13px;">0.2 KB – 2 KB</td>
<td style="border: 1px solid #ddd; padding: 13px;">∞</td>
</tr>
</tbody>
</table>
<table style="border-collapse: collapse; width: 100%; margin-bottom: 2em;">
<thead>
<tr>
<th style="border: 1px solid #ddd; padding: 13px;">Platform</th>
<th style="border: 1px solid #ddd; padding: 13px;">Cost per GB‑Month*</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;">AWS CloudWatch Logs (standard)</td>
<td style="border: 1px solid #ddd; padding: 13px;">$0.50</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;">Azure Log Analytics</td>
<td style="border: 1px solid #ddd; padding: 13px;">$2.76</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;">GCP Cloud Logging (standard)</td>
<td style="border: 1px solid #ddd; padding: 13px;">$0.01</td>
</tr>
</tbody>
</table>
<p style="margin-bottom: 2em; line-height: 1.9;">*Prices as of 2024‑06; regional variations apply.</p>
<p style="margin-bottom: 2em; line-height: 1.9;"><strong>EEFA note:</strong> If you query logs with CloudWatch Insights for compliance, deleting logs before the audit window will break compliance and may incur penalties.</p>
<p style="margin-bottom: 2em; line-height: 1.9;"><strong>Action:</strong> Create a simple spreadsheet listing every log group, workspace, or bucket your workflows use; this inventory becomes the baseline for the steps that follow. Don’t assume the default retention is infinite—it’s just that the service doesn’t auto‑expire.</p>
<hr style="margin: 55px 0; border: none; border-top: 1px solid #eee;" />
<h2 style="margin-bottom: 45px; line-height: 1.3;">2. Trim retention policies to business need</h2>
<h3 style="margin-bottom: 45px; line-height: 1.3;">2.1 AWS – set a short retention for CloudWatch log groups</h3>
<pre style="background: #fafafa; padding: 20px; border: 1px solid #e0e0e0; overflow: auto;"># 7‑day retention for a Step Functions log group
aws logs put-retention-policy \
--log-group-name "/aws/vendedlogs/states/MyStateMachine" \
--retention-in-days 7</pre>
<table style="border-collapse: collapse; width: 100%; margin-bottom: 2em;">
<thead>
<tr>
<th style="border: 1px solid #ddd; padding: 13px;">Retention (days)</th>
<th style="border: 1px solid #ddd; padding: 13px;">Approx. monthly savings*</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;">7</td>
<td style="border: 1px solid #ddd; padding: 13px;">55 %</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;">30</td>
<td style="border: 1px solid #ddd; padding: 13px;">30 %</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;">90</td>
<td style="border: 1px solid #ddd; padding: 13px;">15 %</td>
</tr>
</tbody>
</table>
<p style="margin-bottom: 2em; line-height: 1.9;">*Based on a 10 GB log volume at $0.50/GB‑mo. If you encounter any <a href="/choosing-instance-types-for-n8n-workloads">choosing instance types for n8n workloads </a>resolve them before continuing with the setup.</p>
<h3 style="margin-bottom: 45px; line-height: 1.3;">2.2 Azure – shorten Log Analytics retention</h3>
<pre style="background: #fafafa; padding: 20px; border: 1px solid #e0e0e0; overflow: auto;"># 14‑day retention for a Log Analytics workspace
Set-AzOperationalInsightsWorkspace `
-ResourceGroupName "rg-prod" `
-Name "log-workspace" `
-RetentionInDays 14</pre>
<h3 style="margin-bottom: 45px; line-height: 1.3;">2.3 GCP – lower bucket retention</h3>
<pre style="background: #fafafa; padding: 20px; border: 1px solid #e0e0e0; overflow: auto;"># 10‑day retention for a Cloud Logging bucket
gcloud logging buckets update my-bucket \
--retention-days=10</pre>
<p style="margin-bottom: 2em; line-height: 1.9;"><strong>EEFA warning:</strong> Regulations such as PCI‑DSS or HIPAA often require <strong>≥ 90 days</strong> of retention, so verify your compliance window before tightening policies—most teams forget to adjust retention until the bill arrives, making a double‑check worthwhile.</p>
<p style="margin-bottom: 2em; line-height: 1.9;"><em>Most teams forget to adjust retention until the bill arrives, so it’s worth double‑checking now.</em></p>
<hr style="margin: 55px 0; border: none; border-top: 1px solid #eee;" />
<h2 style="margin-bottom: 45px; line-height: 1.3;">3. Export & archive historical execution logs</h2>
<h3 style="margin-bottom: 45px; line-height: 1.3;">3.1 AWS – export to S3 and move to Glacier</h3>
<pre style="background: #fafafa; padding: 20px; border: 1px solid #e0e0e0; overflow: auto;"># Export the last 90 days of logs to S3
aws logs create-export-task \
--log-group-name "/aws/vendedlogs/states/MyStateMachine" \
--from $(date -d '-90 days' +%s)000 \
--to $(date +%s)000 \
--destination "my-archive-bucket" \
--destination-prefix "step-functions/$(date +%Y-%m-%d)"</pre>
<pre style="background: #fafafa; padding: 20px; border: 1px solid #e0e0e0; overflow: auto;"># Transition the exported objects to Glacier
aws s3 cp s3://my-archive-bucket/step-functions/ \
s3://my-archive-bucket/step-functions-glacier/ \
--recursive --storage-class GLACIER</pre>
<table style="border-collapse: collapse; width: 100%; margin-bottom: 2em;">
<thead>
<tr>
<th style="border: 1px solid #ddd; padding: 13px;">Tier</th>
<th style="border: 1px solid #ddd; padding: 13px;">Retrieval time</th>
<th style="border: 1px solid #ddd; padding: 13px;">Cost/GB‑Month</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;">S3 Standard</td>
<td style="border: 1px solid #ddd; padding: 13px;">Immediate</td>
<td style="border: 1px solid #ddd; padding: 13px;">$0.023</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;">S3 Intelligent‑Tiering</td>
<td style="border: 1px solid #ddd; padding: 13px;">1‑5 min</td>
<td style="border: 1px solid #ddd; padding: 13px;">$0.0125</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;">S3 Glacier</td>
<td style="border: 1px solid #ddd; padding: 13px;">3‑5 hrs (expedited 1‑5 min)</td>
<td style="border: 1px solid #ddd; padding: 13px;">$0.004</td>
</tr>
</tbody>
</table>
<p style="margin-bottom: 2em; line-height: 1.9;">*At this point, moving to Glacier is usually cheaper than trying to prune logs forever.</p>
<h3 style="margin-bottom: 45px; line-height: 1.3;">3.2 Azure – archive to Blob Cool</h3>
<pre style="background: #fafafa; padding: 20px; border: 1px solid #e0e0e0; overflow: auto;"># Run a Log Analytics query and save CSV locally
az monitor log-analytics query \
--workspace "log-workspace" \
--analytics-query "AzureDiagnostics | where TimeGenerated < ago(90d)" \ --output csv > logs_$(date +%Y%m%d).csv</pre>
<pre style="background: #fafafa; padding: 20px; border: 1px solid #e0e0e0; overflow: auto;"># Upload compressed CSV to Cool tier
az storage blob upload \
--account-name mystorage \
--container-name archive \
--name "execution-history/$(date +%Y)/$(date +%m)/logs_$(date +%Y%m%d).csv.gz" \
--file <(gzip -c logs_$(date +%Y%m%d).csv) \
--tier Cool</pre>
<h3 style="margin-bottom: 45px; line-height: 1.3;">3.3 GCP – sink to Cloud Storage Coldline</h3>
<pre style="background: #fafafa; padding: 20px; border: 1px solid #e0e0e0; overflow: auto;"># Create a sink that writes old workflow logs to a bucket
gcloud logging sinks create execution-history-archive \
storage.googleapis.com/my-archive-bucket \
--log-filter='resource.type="cloud_workflows" AND timestamp<"$(date -d "-90 days" --iso-8601)"' \
--include-children</pre>
<pre style="background: #fafafa; padding: 20px; border: 1px solid #e0e0e0; overflow: auto;"># Lifecycle: move to Coldline after 30 days, delete after 365 days
cat > lifecycle.json <<'EOF'
{
"rule": [
{
"action": { "type": "SetStorageClass", "storageClass": "COLDLINE" },
"condition": { "age": 30 }
},
{
"action": { "type": "Delete" },
"condition": { "age": 365 }
}
]
}
EOF
gsutil lifecycle set lifecycle.json gs://my-archive-bucket</pre>
<p style="margin-bottom: 2em; line-height: 1.9;"><strong>EEFA tip:</strong> Compress (gzip) the payload before upload. JSON logs shrink by <strong>70 %‑80 %</strong>, directly reducing storage fees.</p>
<hr style="margin: 55px 0; border: none; border-top: 1px solid #eee;" />
<h2 style="margin-bottom: 45px; line-height: 1.3;">4. Automate ongoing cleanup</h2>
<h3 style="margin-bottom: 45px; line-height: 1.3;">4.1 AWS – Lambda that enforces retention</h3>
<pre style="background: #fafafa; padding: 20px; border: 1px solid #e0e0e0; overflow: auto;">import os, boto3
logs = boto3.client('logs')
RETENTION = int(os.getenv('RETENTION_DAYS', '7'))
def lambda_handler(event, context):
for grp in logs.describe_log_groups()['logGroups']:
name = grp['logGroupName']
if grp.get('retentionInDays') != RETENTION:
logs.put_retention_policy(
logGroupName=name,
retentionInDays=RETENTION
)
return {"status": "ok"}</pre>
<p style="margin-bottom: 2em; line-height: 1.9;">Schedule: daily CloudWatch Event (<code>rate(1 day)</code>)—a daily Lambda is usually enough; sub‑hourly runs are rarely needed.</p>
<h3 style="margin-bottom: 45px; line-height: 1.3;">4.2 Azure – PowerShell runbook</h3>
<pre style="background: #fafafa; padding: 20px; border: 1px solid #e0e0e0; overflow: auto;">workflow Set-LogRetention {
param([int]$RetentionDays = 14)
$ws = Get-AzOperationalInsightsWorkspace -ResourceGroupName "rg-prod"
foreach -parallel ($w in $ws) {
Set-AzOperationalInsightsWorkspace `
-ResourceGroupName $w.ResourceGroupName `
-Name $w.Name `
-RetentionInDays $RetentionDays
}
}</pre>
<p style="margin-bottom: 2em; line-height: 1.9;">Schedule: Azure Automation Scheduler (once per day).</p>
<h3 style="margin-bottom: 45px; line-height: 1.3;">4.3 GCP – Cloud Function triggered by Cloud Scheduler</h3>
<pre style="background: #fafafa; padding: 20px; border: 1px solid #e0e0e0; overflow: auto;"># main.py
import os
from datetime import datetime, timedelta
from google.cloud import logging_v2
client = logging_v2.LoggingServiceV2Client()
RETENTION = int(os.getenv('RETENTION_DAYS', '10'))
def prune_logs(request):
cutoff = datetime.utcnow() - timedelta(days=RETENTION)
filter_str = (
f'timestamp < "{cutoff.isoformat()}Z" '
f'AND resource.type="cloud_workflows"'
)
client.delete_log_entries(filter_=filter_str)
return 'pruned'</pre>
<p style="margin-bottom: 2em; line-height: 1.9;">Schedule: Cloud Scheduler (<code>every 24 hours</code>).</p>
<p style="margin-bottom: 2em; line-height: 1.9;"><strong>EEFA caution:</strong> Deletion APIs are irreversible. Test on a non‑production log group first and keep a 30‑day backup in the archive bucket. If you encounter any <a href="/how-logging-levels-impact-cloud-bills">how logging levels impact cloud bills </a>resolve them before continuing with the setup.</p>
<hr style="margin: 55px 0; border: none; border-top: 1px solid #eee;" />
<h2 style="margin-bottom: 45px; line-height: 1.3;">5. Continuous monitoring & alerting</h2>
<table style="border-collapse: collapse; width: 100%; margin-bottom: 2em;">
<thead>
<tr>
<th style="border: 1px solid #ddd; padding: 13px;">Metric</th>
<th style="border: 1px solid #ddd; padding: 13px;">Threshold</th>
<th style="border: 1px solid #ddd; padding: 13px;">Alert channel</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;">CloudWatch Logs stored bytes (per state machine)</td>
<td style="border: 1px solid #ddd; padding: 13px;">> 5 GB</td>
<td style="border: 1px solid #ddd; padding: 13px;">SNS → Ops Slack</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;">Log Analytics daily ingestion</td>
<td style="border: 1px solid #ddd; padding: 13px;">> 1 GB</td>
<td style="border: 1px solid #ddd; padding: 13px;">Azure Monitor Action Group</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;">GCS bucket size (Coldline)</td>
<td style="border: 1px solid #ddd; padding: 13px;">> 500 GB</td>
<td style="border: 1px solid #ddd; padding: 13px;">Pub/Sub → PagerDuty</td>
</tr>
</tbody>
</table>
<p style="margin-bottom: 2em; line-height: 1.9;"><strong>Sample CloudWatch alarm</strong> – trigger when stored bytes exceed 5 GB:</p>
<pre style="background: #fafafa; padding: 20px; border: 1px solid #e0e0e0; overflow: auto;">aws cloudwatch put-metric-alarm \
--alarm-name "StepFunctionsLogCostSpike" \
--metric-name "IncomingBytes" \
--namespace "AWS/Logs" \
--statistic Sum \
--period 86400 \
--evaluation-periods 1 \
--threshold 5368709120 \
--comparison-operator GreaterThanThreshold \
--alarm-actions arn:aws:sns:us-east-1:123456789012:OpsAlerts</pre>
<p style="margin-bottom: 2em; line-height: 1.9;">*We usually see the 5 GB threshold crossed after a few weeks of heavy traffic.</p>
<hr style="margin: 55px 0; border: none; border-top: 1px solid #eee;" />
<h2 style="margin-bottom: 45px; line-height: 1.3;">6. Best‑practice checklist</h2>
<table style="border-collapse: collapse; width: 100%; margin-bottom: 2em;">
<thead>
<tr>
<th style="border: 1px solid #ddd; padding: 13px; width: 30px;">Steps</th>
<th style="border: 1px solid #ddd; padding: 13px;">Action</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;">1</td>
<td style="border: 1px solid #ddd; padding: 13px;">Inventory every execution‑history destination (CloudWatch, Log Analytics, Cloud Logging).</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;">2</td>
<td style="border: 1px solid #ddd; padding: 13px;">Align retention with compliance – keep logs only as long as required.</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;">3</td>
<td style="border: 1px solid #ddd; padding: 13px;">Export logs older than the retention window to a cheap archive tier (Glacier, Blob Cool/Archive, Coldline).</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;">4</td>
<td style="border: 1px solid #ddd; padding: 13px;">Compress exported files (gzip, zstd) before archiving.</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;">5</td>
<td style="border: 1px solid #ddd; padding: 13px;">Deploy an automated retention‑enforcer (Lambda, Automation Runbook, Cloud Function).</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;">6</td>
<td style="border: 1px solid #ddd; padding: 13px;">Add bucket lifecycle rules: hot → cold → delete.</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;">7</td>
<td style="border: 1px solid #ddd; padding: 13px;">Enable cost‑monitoring dashboards and threshold alerts per platform.</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;">8</td>
<td style="border: 1px solid #ddd; padding: 13px;">Perform a quarterly audit – verify archive integrity, confirm compliance windows, adjust thresholds.</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;">9</td>
<td style="border: 1px solid #ddd; padding: 13px;">Document the workflow in your runbook and link to the <strong>Serverless Cost Optimization Pillar</strong>.</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 13px;">10</td>
<td style="border: 1px solid #ddd; padding: 13px;">Review provider price‑change announcements (e.g., AWS Log Data‑Ingestion) and update policies.</td>
</tr>
</tbody>
</table>
<hr style="margin: 55px 0; border: none; border-top: 1px solid #eee;" />
<h2 style="margin-bottom: 45px; line-height: 1.3;">Conclusion</h2>
<p style="margin-bottom: 2em; line-height: 1.9;">By tightening retention, off‑loading stale execution history to ultra‑cheap archive tiers, and automating the pipeline, you can slash storage‑related spend on server‑less logs by up to <strong>80 %</strong>. The approach keeps you audit‑ready, avoids surprise cost spikes, and only a few scheduled scripts run themselves. Apply the checklist, monitor the metrics, and you’ll keep execution‑history costs predictable and low in production.</p>
Step by Step Guide to solve storage cost optimization execution history
Who this is for: Ops engineers, DevOps leads, or SREs managing server‑less workflows (Step Functions, Durable Functions, Cloud Run jobs, etc.) who see execution‑history storage driving up their monthly bill. We cover this in detail in the n8n Cost, Scaling & Infrastructure Economics Guide.
Quick diagnosis
Server‑less workflows automatically write execution‑history records to a log service (CloudWatch Logs, Azure Log Analytics, GCP Logging). If storage costs climb, the usual suspects are:
Retention longer than required.
Uncompressed logs staying in a hot tier.
No archiving strategy for older data.
Pulling those three levers usually cuts storage spend by 40 %–80 %, and you still keep auditability. In production, the creep shows up after the first billing cycle.
EEFA note: If you query logs with CloudWatch Insights for compliance, deleting logs before the audit window will break compliance and may incur penalties.
Action: Create a simple spreadsheet listing every log group, workspace, or bucket your workflows use; this inventory becomes the baseline for the steps that follow. Don’t assume the default retention is infinite—it’s just that the service doesn’t auto‑expire.
2. Trim retention policies to business need
2.1 AWS – set a short retention for CloudWatch log groups
# 7‑day retention for a Step Functions log group
aws logs put-retention-policy \
--log-group-name "/aws/vendedlogs/states/MyStateMachine" \
--retention-in-days 7
# 14‑day retention for a Log Analytics workspace
Set-AzOperationalInsightsWorkspace `
-ResourceGroupName "rg-prod" `
-Name "log-workspace" `
-RetentionInDays 14
2.3 GCP – lower bucket retention
# 10‑day retention for a Cloud Logging bucket
gcloud logging buckets update my-bucket \
--retention-days=10
EEFA warning: Regulations such as PCI‑DSS or HIPAA often require ≥ 90 days of retention, so verify your compliance window before tightening policies—most teams forget to adjust retention until the bill arrives, making a double‑check worthwhile.
Most teams forget to adjust retention until the bill arrives, so it’s worth double‑checking now.
3. Export & archive historical execution logs
3.1 AWS – export to S3 and move to Glacier
# Export the last 90 days of logs to S3
aws logs create-export-task \
--log-group-name "/aws/vendedlogs/states/MyStateMachine" \
--from $(date -d '-90 days' +%s)000 \
--to $(date +%s)000 \
--destination "my-archive-bucket" \
--destination-prefix "step-functions/$(date +%Y-%m-%d)"
# Transition the exported objects to Glacier
aws s3 cp s3://my-archive-bucket/step-functions/ \
s3://my-archive-bucket/step-functions-glacier/ \
--recursive --storage-class GLACIER
Tier
Retrieval time
Cost/GB‑Month
S3 Standard
Immediate
$0.023
S3 Intelligent‑Tiering
1‑5 min
$0.0125
S3 Glacier
3‑5 hrs (expedited 1‑5 min)
$0.004
*At this point, moving to Glacier is usually cheaper than trying to prune logs forever.
3.2 Azure – archive to Blob Cool
# Run a Log Analytics query and save CSV locally
az monitor log-analytics query \
--workspace "log-workspace" \
--analytics-query "AzureDiagnostics | where TimeGenerated < ago(90d)" \ --output csv > logs_$(date +%Y%m%d).csv
# Create a sink that writes old workflow logs to a bucket
gcloud logging sinks create execution-history-archive \
storage.googleapis.com/my-archive-bucket \
--log-filter='resource.type="cloud_workflows" AND timestamp<"$(date -d "-90 days" --iso-8601)"' \
--include-children
EEFA caution: Deletion APIs are irreversible. Test on a non‑production log group first and keep a 30‑day backup in the archive bucket. If you encounter any how logging levels impact cloud bills resolve them before continuing with the setup.
By tightening retention, off‑loading stale execution history to ultra‑cheap archive tiers, and automating the pipeline, you can slash storage‑related spend on server‑less logs by up to 80 %. The approach keeps you audit‑ready, avoids surprise cost spikes, and only a few scheduled scripts run themselves. Apply the checklist, monitor the metrics, and you’ll keep execution‑history costs predictable and low in production.