AWSAmazon S3Storage

aws_s3_bucket_acl cost estimation

Sets the access control list on an S3 bucket. The ACL configuration is free. The bucket it governs bills for storage, requests, and data transfer, which is where all S3 cost lives.

The aws_s3_bucket_acl resource manages the access control list (ACL) on an S3 bucket. Since the 2018 provider split, ACLs live in their own resource rather than inline on aws_s3_bucket. Setting an ACL is a control-plane operation and is completely free, there is no charge for defining or changing who can read or write a bucket.

All S3 cost sits in the bucket the ACL points at, not the ACL itself. S3 bills on three main axes: storage (from about 0.023 dollars per GB-month for S3 Standard in us-east-1, dropping through Standard-IA, One Zone-IA, Glacier Instant Retrieval, and Deep Archive), requests (about 0.0005 dollars per 1,000 GET requests and 0.005 dollars per 1,000 PUT requests for Standard), and data transfer out to the internet (about 0.09 dollars per GB after the free tier). An ACL that accidentally makes a bucket public can turn a private storage bill into a runaway data transfer bill if the objects are then downloaded at scale, so the ACL is cost-adjacent even though it is free.

Modern AWS guidance is to disable ACLs entirely. The recommended default is S3 Object Ownership set to BucketOwnerEnforced, which makes ACLs inoperative and forces all access control through bucket policies and IAM. In that mode you do not create an aws_s3_bucket_acl at all. ACLs remain relevant mainly for legacy buckets, cross-account object delivery patterns (such as CloudFront or ELB log delivery), and buckets that still rely on canned ACLs like log-delivery-write.

The security-to-cost link is direct: a public-read ACL combined with a public object is the classic way a leaked or crawled bucket generates unexpected request and egress charges. Pair any ACL work with aws_s3_bucket_public_access_block to prevent accidental exposure. c3x reports aws_s3_bucket_acl as free and attributes all spend to the underlying aws_s3_bucket.

Terraform example

A minimal but realistic configuration that C3X can estimate.

resource "aws_s3_bucket" "logs" {
  bucket = "my-app-access-logs"
}

resource "aws_s3_bucket_ownership_controls" "logs" {
  bucket = aws_s3_bucket.logs.id
  rule {
    object_ownership = "BucketOwnerPreferred"
  }
}

# ACL is only needed here because log delivery writes cross-account objects.
resource "aws_s3_bucket_acl" "logs" {
  depends_on = [aws_s3_bucket_ownership_controls.logs]
  bucket     = aws_s3_bucket.logs.id
  acl        = "log-delivery-write"
}

Pricing dimensions

What you actually pay for when you provision aws_s3_bucket_acl.

DimensionUnitWhat's being charged
S3 bucket ACLfreeDefining or changing a bucket ACL is a free control-plane operation.
$0 (free)
S3 Standard storageper GB-monthStorage in the underlying bucket, tiered by volume and storage class.
$0.023 per GB-month (Standard, us-east-1)
S3 requestsper 1,000 requestsGET, PUT, and other requests against the bucket. A public ACL that exposes objects can multiply GET volume.
$0.0005 per 1,000 GET, $0.005 per 1,000 PUT
S3 data transfer outper GBEgress to the internet after the free tier, the biggest surprise cost if a bucket is made public.
$0.09 per GB (first 10 TB/month, us-east-1)

Optimization tips

Common ways to reduce aws_s3_bucket_acl cost without changing the workload.

Disable ACLs with BucketOwnerEnforced

For new buckets set Object Ownership to BucketOwnerEnforced and skip aws_s3_bucket_acl entirely. Access control moves to bucket policies and IAM, which is simpler to audit and removes a common path to accidental public exposure.

Never combine a public-read ACL with public objects unintentionally

A public ACL is free but the download traffic it enables is not. Attach aws_s3_bucket_public_access_block so a stray canned ACL cannot silently expose objects and generate egress charges.

Use ACLs only for legacy cross-account delivery

Canned ACLs like log-delivery-write are still required for some AWS service log delivery. Limit ACL usage to those specific buckets and use policies everywhere else.

Front public content with CloudFront

Lower egress rate plus reduced S3 GET charges

If objects must be served publicly, put CloudFront in front of the bucket. CloudFront egress is often cheaper than direct S3 egress at scale and caching cuts origin request volume.

FAQ

Does an S3 bucket ACL cost anything?

No. Setting or changing an ACL is a free control-plane operation. All S3 cost comes from storage, requests, and data transfer in the bucket the ACL governs.

Should I still use ACLs on new buckets?

Generally no. AWS recommends disabling ACLs with Object Ownership set to BucketOwnerEnforced and managing access through bucket policies and IAM. ACLs remain necessary only for legacy patterns like cross-account log delivery.

Can an ACL cause a surprise bill?

Indirectly, yes. An ACL that makes objects publicly readable is free itself, but if those objects are then downloaded at scale the resulting request and data transfer charges can be large. Combine ACL settings with a public access block to avoid this.

Why is the ACL a separate Terraform resource now?

The AWS provider split bucket sub-configurations into standalone resources so they can be managed independently. ACL, versioning, encryption, lifecycle, and logging each became their own resource, all free, attached to the paid aws_s3_bucket.

Related resources

Estimate this resource in your own Terraform

Free, open source, no API key. C3X parses your Terraform and shows line-item cost for every resource, including aws_s3_bucket_acl.