# Large S3 Bucket With External Access -- Consider Requester Pays

> S3 buckets over the 1 TiB size floor with public access enabled and Requester Pays off are pre-filtered as candidates, but ZopNight abstains on all of them today. The saving would be external egress GB and GET requests shifted to requesters, yet no authoritative per-bucket producer exists, and a fabricated figure is banned.

Source: https://zop.dev/integrations/aws/recommendations/large-s3-bucket-with-external-access-consider-requester-pays
Updated: 2026-08-19

---

## Public access on a bucket over 1 TiB

- Metadata["requester_pays"] (bool, s3.go:675): skip when already enabled.
- Metadata["public_access_enabled"] (bool, s3.go:455/458), the external-access gate (a superset proxy; the prior external_access Tag was never written). Fail-closed when absent.
- size gate: sum of Metadata["storageClasses"] class→GB ≥ 1024 GB (1 TiB floor; the prior size_large Tag was never written).
- PRODUCER-GAP: external_data_transfer_out_gb (monthly external DataTransfer-Out GB) and external_get_requests (monthly external GET/SELECT count): the per-bucket cross-account/anonymous egress quantities. No authoritative producer today.

## The egress quantities no producer supplies

concrete-or-abstain (cost-driven rightsizing). The concrete saving is the external egress that shifts to the requester: SavingsUSD = external_data_transfer_out_gb × egressRate + external_get_requests × requestRate, at [S3's published data-transfer and request rates](https://aws.amazon.com/s3/pricing/). Those quantities are unquantifiable from any authoritative, non-tag, lightweight source today (see (a)/(b)/(c)), so Part A abstains (returns nil) instead of emitting the banned $0 advisory or the over-counted aggregate; the size/public/not-already-enabled gates are retained as real pre-filters. Close condition (Part B): land external_data_transfer_out_gb/external_get_requests per bucket from source (c) (Requester-field-classified access-log/CloudTrail analytics, gated on that logging being enabled), then fire concretely on SavingsUSD >= floor. (The prior code returned Category="advisory" SavingsUSD=0 specifically so shouldDropLowSavings would not drop it, which is the banned advisory-dump for a cost lever; the category is corrected to the true cost-driven axis.)

## Turning on Requester Pays

1. Verify external consumers can authenticate with AWS credentials
2. Enable Requester Pays on the bucket
3. Notify consumers that they must include x-amz-request-payer in requests
4. Monitor for access errors from consumers not using the header
