CloudFront – Consider Setting a Default Root Object

CloudFront – Consider Setting a Default Root Object

CloudFront distributions should have a default root object configured to prevent user access errors and reduce unnecessary costs. The default root object is the file that CloudFront returns when users access your distribution’s root URL without specifying a particular file. Without this configuration, users may encounter 403 or 404 errors, leading to poor user experience and potential revenue loss.

Why This Policy Matters

Cost Impact and User Experience

CloudFront distributions without a default root object create several financial and operational challenges:

  • Error Response Costs: When users access your root URL without a default object configured, CloudFront may return error responses. These errors still consume bandwidth and generate charges, but provide no value to your users or business.

  • Origin Load Increase: Without proper default object configuration, your origin servers may receive more requests as CloudFront attempts to resolve undefined paths, increasing compute and bandwidth costs at the origin level.

  • Support and Troubleshooting Overhead: User-reported access issues require engineering time to investigate and resolve, adding operational costs to your infrastructure team.

How It Reduces Costs

Implementing a default root object policy delivers cost savings through several mechanisms:

  • Reduced error responses: Eliminates unnecessary bandwidth charges for error pages

  • Lower origin requests: Decreases the number of requests hitting your origin infrastructure

  • Decreased support tickets: Prevents user-reported access issues that require investigation

  • Improved cache efficiency: Enables better caching strategies for your main landing page

Potential Savings Examples

Consider a typical web application receiving 100,000 root URL requests monthly:

Without default root object:

100,000 error responses at $0.085 per GB (US/EU) = ~$8.50/month in wasted bandwidth

Additional origin requests for error handling = ~$5-15/month depending on origin type

Engineering time for troubleshooting = 2-4 hours monthly ($200-400 in opportunity cost)

Total monthly waste: $213-423 per 100,000 requests

With default root object:

Proper content delivery with efficient caching

Reduced origin load

Zero error-related support overhead

For organizations with multiple distributions or higher traffic volumes, these savings scale significantly.

Implementation Guide

Infrastructure-as-Code Example

Here’s how to properly configure a default root object in Terraform:

Problematic Configuration:

resource "aws_cloudfront_distribution" "example" {
  origin {
    domain_name = "example.com"
    origin_id   = "example-origin"
   
    custom_origin_config {
      http_port              = 80
      https_port             = 443
      origin_protocol_policy = "https-only"
      origin_ssl_protocols   = ["TLSv1.2"]
    }
  }
default_cache_behavior {
    target_origin_id       = "example-origin"
    viewer_protocol_policy = "redirect-to-https"
    allowed_methods        = ["GET", "HEAD"]
    cached_methods         = ["GET", "HEAD"]
   
    forwarded_values {
      query_string = false
      cookies {
        forward = "none"
      }
    }
  }
enabled = true
 
  # Missing default_root_object configuration
}
resource "aws_cloudfront_distribution" "example" {
  origin {
    domain_name = "example.com"
    origin_id   = "example-origin"
   
    custom_origin_config {
      http_port              = 80
      https_port             = 443
      origin_protocol_policy = "https-only"
      origin_ssl_protocols   = ["TLSv1.2"]
    }
  }
default_cache_behavior {
    target_origin_id       = "example-origin"
    viewer_protocol_policy = "redirect-to-https"
    allowed_methods        = ["GET", "HEAD"]
    cached_methods         = ["GET", "HEAD"]
   
    forwarded_values {
      query_string = false
      cookies {
        forward = "none"
      }
    }
  }
enabled = true
 
  # Missing default_root_object configuration
}
resource "aws_cloudfront_distribution" "example" {
  origin {
    domain_name = "example.com"
    origin_id   = "example-origin"
   
    custom_origin_config {
      http_port              = 80
      https_port             = 443
      origin_protocol_policy = "https-only"
      origin_ssl_protocols   = ["TLSv1.2"]
    }
  }
default_cache_behavior {
    target_origin_id       = "example-origin"
    viewer_protocol_policy = "redirect-to-https"
    allowed_methods        = ["GET", "HEAD"]
    cached_methods         = ["GET", "HEAD"]
   
    forwarded_values {
      query_string = false
      cookies {
        forward = "none"
      }
    }
  }
enabled = true
 
  # Missing default_root_object configuration
}

Corrected Configuration:

resource "aws_cloudfront_distribution" "example" {
  origin {
    domain_name = "example.com"
    origin_id   = "example-origin"
   
    custom_origin_config {
      http_port              = 80
      https_port             = 443
      origin_protocol_policy = "https-only"
      origin_ssl_protocols   = ["TLSv1.2"]
    }
  }
default_cache_behavior {
    target_origin_id       = "example-origin"
    viewer_protocol_policy = "redirect-to-https"
    allowed_methods        = ["GET", "HEAD"]
    cached_methods         = ["GET", "HEAD"]
   
    forwarded_values {
      query_string = false
      cookies {
        forward = "none"
      }
    }
  }
enabled             = true
  default_root_object = "index.html"  # Added default root object
 
  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }
 
  viewer_certificate {
    cloudfront_default_certificate = true
  }
}
resource "aws_cloudfront_distribution" "example" {
  origin {
    domain_name = "example.com"
    origin_id   = "example-origin"
   
    custom_origin_config {
      http_port              = 80
      https_port             = 443
      origin_protocol_policy = "https-only"
      origin_ssl_protocols   = ["TLSv1.2"]
    }
  }
default_cache_behavior {
    target_origin_id       = "example-origin"
    viewer_protocol_policy = "redirect-to-https"
    allowed_methods        = ["GET", "HEAD"]
    cached_methods         = ["GET", "HEAD"]
   
    forwarded_values {
      query_string = false
      cookies {
        forward = "none"
      }
    }
  }
enabled             = true
  default_root_object = "index.html"  # Added default root object
 
  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }
 
  viewer_certificate {
    cloudfront_default_certificate = true
  }
}
resource "aws_cloudfront_distribution" "example" {
  origin {
    domain_name = "example.com"
    origin_id   = "example-origin"
   
    custom_origin_config {
      http_port              = 80
      https_port             = 443
      origin_protocol_policy = "https-only"
      origin_ssl_protocols   = ["TLSv1.2"]
    }
  }
default_cache_behavior {
    target_origin_id       = "example-origin"
    viewer_protocol_policy = "redirect-to-https"
    allowed_methods        = ["GET", "HEAD"]
    cached_methods         = ["GET", "HEAD"]
   
    forwarded_values {
      query_string = false
      cookies {
        forward = "none"
      }
    }
  }
enabled             = true
  default_root_object = "index.html"  # Added default root object
 
  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }
 
  viewer_certificate {
    cloudfront_default_certificate = true
  }
}

Manual Configuration Steps

For existing CloudFront distributions through the AWS Console:

Navigate to CloudFront Console

Log into AWS Management Console

Go to CloudFront service

Select your distribution

Edit Distribution Settings

Click on the distribution ID

Select the “General” tab

Click “Edit”

  • Configure Default Root Object

  • Locate the “Default Root Object” field

  • Enter your default file (typically index.html)

Click “Yes, Edit”

Wait for Deployment

  • Distribution status will show “In Progress”

  • Wait for deployment to complete (typically 5-15 minutes)

Best Practices

File Selection:

  • Use index.html for static websites

  • Use index.php for PHP applications

  • Consider default.aspx for .NET applications

  • Ensure the file exists at your origin

Testing and Validation:

Test root URL access after configuration

Verify caching behavior works as expected

Monitor CloudWatch metrics for error rate reduction

Check origin request patterns

Multi-Environment Considerations:

  • Use consistent default objects across environments

  • Document default root object choices in infrastructure documentation

  • Include default root object configuration in CI/CD pipeline templates

Tools and Scripts

This policy is fully supported in Infracost, which enables you to scan your codebase and identify CloudFront distributions missing default root objects. Infracost offers a free trial that allows you to detect these cost optimization opportunities before they impact production workloads. By integrating Infracost into your development workflow, you can prevent these issues from reaching production and systematically address existing instances across your infrastructure.

AWS CLI Script for Bulk Updates:

#!/bin/bash

Script to check and update CloudFront distributions

aws cloudfront list-distributions --query 'DistributionList.Items[?DefaultRootObject==null].[Id,DomainName]' --output table

Update specific distribution (replace DISTRIBUTION_ID)

aws cloudfront get-distribution-config --id DISTRIBUTION_ID > config.json

Edit config.json to add DefaultRootObject

aws cloudfront update-distribution --id DISTRIBUTION_ID --distribution-config file://config.json --if-match ETAG

Considerations and Caveats

  • When This Policy May Not Apply

  • API-Only Distributions: CloudFront distributions serving only API endpoints may not require default root objects, as they don’t expect root URL access patterns.

  • Custom Routing Logic: Applications with complex routing mechanisms may handle root requests differently, making default objects unnecessary.

  • Redirect-Only Distributions: Distributions configured purely for redirects to other domains might not benefit from default root objects.

Potential Drawbacks

  • File Availability: The specified default root object must exist at your origin. Missing files will still generate 404 errors.

  • Caching Implications: Default root objects are cached according to your distribution’s caching behavior, which may not align with your application’s requirements for the root path.

  • SEO Considerations: Ensure your default root object aligns with your SEO strategy and canonical URL structure.

Implementation Challenges

  • Legacy Applications: Older applications may have different file structures or naming conventions that require careful consideration when selecting default objects.

  • Multi-Language Sites: Websites supporting multiple languages may need more complex routing logic rather than simple default objects.

  • Dynamic Content: Applications serving primarily dynamic content may need to carefully consider caching implications of their chosen default object.

Monitoring and Maintenance

Key Metrics to Track

  • 4xx error rates before and after implementation

  • Origin request patterns to verify reduced load

  • Cache hit ratios for root path requests

  • User experience metrics like bounce rates from the root URL

Ongoing Maintenance

  • Regular audits of new distributions to ensure policy compliance

  • Documentation updates when default objects change

  • Testing procedures for validating default object functionality

  • Monitoring alerts for increases in 4xx errors that might indicate issues

Create Free Account

This policy is supported in Infracost and available in the free trial. Sign up today and scan your code using our entire library of FinOps policies.

Get started
with Infracost

© 2026 Infracost Inc

Manage cookies

Get started
with Infracost

© 2026 Infracost Inc

Manage cookies

Get started
with Infracost

© 2026 Infracost Inc

Manage cookies