Use case

Test Report Storage Costs Getting Out of Control? Here's the Fix

S3 bills growing every month from old test reports? See why DIY storage gets expensive and how automatic per-project retention reduces the storage you pay for.

On this page

You set up an S3 bucket to store test reports. Smart move. Now you have historical data. Six months later, the storage bill is 10x what you expected.

The Hidden Cost of “Just Store It”

When teams outgrow CI artifact storage, the natural solution is cloud storage:

- name: Upload to S3
run: aws s3 cp ./test-results s3://test-reports/${{ github.sha }} --recursive

Simple. Effective. And a ticking time bomb for your cloud bill.

Why Storage Costs Compound

Unlike compute (which stops billing when idle), storage bills accumulate:

MonthNew ReportsTotal StoredMonthly Cost*
150 GB50 GB$1.15
350 GB150 GB$3.45
650 GB300 GB$6.90
1250 GB600 GB$13.80
2450 GB1.2 TB$27.60

*S3 Standard pricing at $0.023/GB

That’s assuming steady growth. Teams that scale up CI runs or add more test suites see exponential increases.

The Playwright Problem

E2E testing frameworks like Playwright make storage costs explode. A typical Playwright setup generates:

  • Screenshots on failure: 200KB–2MB each
  • Video recordings: 5–50MB per test
  • Trace files: 10–100MB per test run

A team running 100 E2E tests across 3 browsers, 4 times per day:

Artifact TypeSize per RunDailyMonthly
HTML Report5 MB20 MB600 MB
Screenshots50 MB200 MB6 GB
Videos500 MB2 GB60 GB
Traces200 MB800 MB24 GB
Total755 MB~3 GB~90 GB

That’s 90 GB per month from one project. Most teams have multiple. And nobody wants to disable recordings: they’re essential for debugging flaky tests.

DIY Cleanup: Harder Than It Looks

“We’ll just write a cleanup script.” Famous last words.

Lifecycle Rules Look Simple

<LifecycleConfiguration>
<Rule>
<Expiration>
<Days>90</Days>
</Expiration>
<Filter>
<Prefix>test-reports/</Prefix>
</Filter>
</Rule>
</LifecycleConfiguration>

But Reality Is Messy

Problem 1: One-size-fits-all doesn’t work

Your main branch test reports are critical for debugging production issues. Feature branch reports are disposable after merge. S3 lifecycle rules can’t distinguish between them without complex prefix schemes.

Problem 2: Accidental deletion

A misconfigured rule deleted 6 months of production test history. Now you’re explaining to leadership why you can’t investigate that customer-reported bug from Q2.

Problem 3: Cost visibility

You need to know what you will be billed. S3 doesn’t tell you what your report storage costs or where that cost is heading without additional tooling (CloudWatch, Cost Explorer tags, third-party analytics).

Problem 4: Access control

Who can view reports? S3 bucket policies are notoriously tricky. Teams end up either too permissive (security risk) or too restrictive (people can’t access what they need).

What Teams Actually Need

Storing test reports long term comes down to five requirements:

  1. Automatic cleanup - Old reports deleted without manual intervention
  2. Per-project control - Different retention for different projects
  3. Visible costs - See total storage and projected overage before the bill arrives
  4. Easy access - Browse and share reports without S3 permissions
  5. No maintenance - No scripts to write, debug, or update

How Gaffer Solves Storage Costs

Gaffer is purpose-built for test report hosting. Storage management is built in, not bolted on.

Automatic Cleanup by Default

Every plan includes automatic cleanup based on your retention period:

PlanDefault RetentionStorage Included
Free7 days500 MB
Pro30 days10 GB
Team90 days50 GB

Old reports are automatically deleted. No lifecycle rules to configure. No scripts to maintain.

Per-Project Retention

Not all projects are equal. Configure retention per-project:

  • Noisy or short-lived suites: 7 days
  • Suites you debug production from: 90 days
  • Compliance projects: Unlimited (paid plans can disable cleanup)

Retention applies to a whole project, not to a branch. To keep feature branch reports for less time than main, upload them to a separate project with its own token.

# Your CI stays simple
- name: Upload to Gaffer
uses: gaffer-sh/gaffer-uploader@v2
with:
gaffer_upload_token: ${{ secrets.GAFFER_PROJECT_TOKEN }}
report_path: ./test-results

Retention is configured in the Gaffer dashboard, not your CI pipeline.

What Storage Over the Limit Costs

Storage over your plan limit is billed at $0.50/GB/month on Pro and Team, measured on the 1st of each month and rounded up to the next GB. Free has no overage because uploads over quota are refused. The bill grows with stored bytes, so retention is how you bound it.

Example scenario:

  • Team plan: 50 GB included
  • Actual usage: 65 GB
  • Overage: 15 GB × $0.50 = $7.50 extra

Compare that to debugging S3 cost spikes across multiple buckets and projects.

Cost Visibility Built In

The billing page (Settings > Billing) shows total storage used against your plan limit and warns you at 90% of the limit. Once you pass the limit, it shows projected overage in GB and dollars.

Usage is tracked per organization, not per project.

No CloudWatch dashboards or Cost Explorer tags required.

Migration Is Painless

Already have test reports in S3? You don’t need to migrate anything:

  1. Add Gaffer upload to CI (5 minutes)
  2. New reports go to Gaffer automatically
  3. Old S3 reports stay where they are (or delete them to save costs)
  4. Over time, Gaffer becomes your source of truth

Your S3 bucket can run down naturally while Gaffer handles new reports.

When to Keep S3

Gaffer isn’t the right fit for everyone:

  • Raw build artifacts (binaries, packages) → Keep in S3/artifact storage
  • Compliance archives requiring specific certifications → Use compliant storage
  • Existing tooling that depends on S3 paths → Evaluate migration cost

For test reports specifically (HTML reports, JUnit XML, JSON results), Gaffer is purpose-built: retention, usage and overage tracking, and share links come with the plan.

S3 vs Gaffer for Test Reports

S3 is great for general-purpose storage. It’s not optimized for test reports.

ConcernS3 DIYGaffer
Automatic cleanupManual lifecycle rulesBuilt-in
Per-project retentionComplex prefix schemesDashboard toggle
Storage cost$0.023/GB/month on everything you keepPlan price, plus $0.50/GB/month over the limit on Pro and Team
Access controlBucket policiesTeam-based permissions
Setup timeHours to days5 minutes
MaintenanceOngoingZero

Get Started

Gaffer deletes reports once they pass retention, so stored data levels off instead of accumulating. Upload more and you store more: per-project retention is how you keep that under the plan limit.