Hugo Caching Strategies for Performance

Optimize developing and running Hugo sites

Page content

Hugo caching strategies are essential for maximizing the performance of your static site generator. While Hugo generates static files that are inherently fast, implementing proper caching at multiple layers can dramatically improve build times, reduce server load, and enhance user experience.

Whether you’re using a popular theme from our Most popular themes for Hugo guide or a custom theme, these caching strategies will help optimize your site’s performance.

This comprehensive guide covers build-time caching, incremental builds, CDN optimization, HTTP headers, and asset caching strategies to help you achieve optimal performance for your Hugo-based website.

chef-in-a-white with Caching Strategies This nice image is generated by AI model Flux 1 dev.

Understanding Hugo’s Build Cache

Hugo maintains an internal build cache that stores processed content and assets to speed up subsequent builds. This cache is located in the resources/_gen directory and includes:

  • Rendered templates: Pre-processed template output
  • Processed images: Resized, optimized, and converted images
  • Compiled assets: Minified CSS and JavaScript
  • Resource metadata: File hashes and processing results

How Build Cache Works

When you run hugo, the generator:

  1. Checks the cache for existing processed resources
  2. Compares file modification times and content hashes
  3. Skips processing unchanged files
  4. Only rebuilds modified or new content

This means that for a site with 1000 posts, editing a single post only requires Hugo to process that one post and regenerate affected pages, not the entire site.

Managing the Build Cache

You can control Hugo’s cache behavior using various command-line flags. For a comprehensive reference of Hugo commands, see the Hugo Cheat Sheet:

# Clear the cache and rebuild everything
hugo --ignoreCache

# Use a custom cache directory
export HUGO_CACHEDIR=/path/to/cache
hugo

# Disable fast render mode (forces full rebuild)
hugo server --disableFastRender

For CI/CD pipelines, consider persisting the cache directory between builds to speed up deployments. If you’re using Gitea Actions for deployment, see our guide on Using Gitea Actions deploy Hugo website to AWS S3 for a complete CI/CD setup:

# Example GitHub Actions workflow
- name: Cache Hugo resources
  uses: actions/cache@v3
  with:
    path: resources/_gen
    key: ${{ runner.os }}-hugo-${{ hashFiles('**/content/**') }}

Configuring File Caches

Hugo provides granular control over different cache types through the [caches] configuration section. According to the Hugo documentation, you can configure multiple cache types:

[caches]
  [caches.assets]
    dir = ':resourceDir/_gen'
    maxAge = -1
  [caches.getcsv]
    dir = ':cacheDir/:project'
    maxAge = -1
  [caches.getjson]
    dir = ':cacheDir/:project'
    maxAge = -1
  [caches.getresource]
    dir = ':cacheDir/:project'
    maxAge = -1
  [caches.images]
    dir = ':resourceDir/_gen'
    maxAge = -1
  [caches.misc]
    dir = ':cacheDir/:project'
    maxAge = -1
  [caches.modules]
    dir = ':cacheDir/modules'
    maxAge = -1

Cache Types Explained

  • assets: Caches processed CSS, JavaScript, and other assets from Hugo Pipes
  • getcsv: Caches parsed CSV files loaded via getCSV function
  • getjson: Caches parsed JSON files loaded via getJSON function
  • getresource: Caches remote resources fetched via getResource function
  • images: Caches processed images (resized, optimized, converted)
  • misc: General-purpose cache for miscellaneous operations
  • modules: Caches Hugo modules and their dependencies

Configuration Options

Each cache type supports two configuration options:

  • dir: The absolute file system path where cached files are stored. You can use tokens:

    • :cacheDir - Replaced with the configured cache directory
    • :resourceDir - Replaced with the resource directory (typically resources/_gen)
    • :project - Replaced with the base directory name of the current Hugo project
  • maxAge: The duration a cached entry remains valid before being evicted:

    • 0 - Disables the cache
    • -1 - Cache entry never expires (default)
    • Positive number - Cache expires after specified duration (e.g., 3600 for 1 hour)

Custom Cache Configuration Example

You can customize cache settings for specific use cases:

[caches]
  # Keep processed images cached indefinitely
  [caches.images]
    dir = ':resourceDir/_gen/images'
    maxAge = -1
  
  # Cache JSON API responses for 1 hour
  [caches.getjson]
    dir = ':cacheDir/:project/json'
    maxAge = 3600
  
  # Cache remote resources for 24 hours
  [caches.getresource]
    dir = ':cacheDir/:project/resources'
    maxAge = 86400

This configuration allows you to:

  • Keep processed images cached permanently (since they’re deterministic)
  • Refresh JSON data every hour (for dynamic content)
  • Cache remote resources for 24 hours (balance between freshness and performance)

The :project token ensures each Hugo project has isolated caches, so running hugo --gc (garbage collection) only affects the current project’s cache.

Incremental Builds

Hugo’s incremental build system is one of its most powerful features. It tracks changes at the file level and only rebuilds what’s necessary.

Enabling Incremental Builds

Incremental builds are enabled by default. Hugo automatically:

  • Tracks file dependencies
  • Rebuilds only changed pages and their dependencies
  • Maintains dependency graphs for efficient updates

Build Performance Tips

  1. Use hugo server for development: The development server uses incremental builds automatically
  2. Leverage --minify only in production: Minification adds overhead; use it only for final builds
  3. Optimize image processing: Use Hugo’s image processing features efficiently:
[imaging]
  bgColor = '#ffffff'
  hint = 'photo'
  quality = 75
  resampleFilter = 'box'
  1. Limit resource processing: Only process images and assets that are actually used

CDN Caching Strategies

Content Delivery Networks (CDNs) are crucial for global performance. When deploying Hugo sites to CDNs like CloudFront, Cloudflare, or Netlify, configure caching appropriately. For detailed instructions on deploying your Hugo site to AWS S3 with CloudFront, see our guide on Deploy Hugo-generated website to AWS S3.

CloudFront Configuration

For AWS CloudFront deployments, configure cache behaviors:

# config.toml
[[deployment.targets]]
name = "production"
URL = "s3://your-bucket?region=us-east-1"
cloudFrontDistributionID = "E1XIDGUJGD9BU9"

Create CloudFront cache behaviors:

  • Static assets (.css, .js, .jpg, .png, etc.):

    • TTL: 1 year (31536000 seconds)
    • Cache Policy: CachingOptimized
    • Compress: Yes
  • HTML pages (.html):

    • TTL: 1 hour (3600 seconds)
    • Cache Policy: CachingDisabled (with origin headers)
    • Compress: Yes

Cache Invalidation

Automate cache invalidation on deployments:

# Invalidate CloudFront cache after deployment
aws cloudfront create-invalidation \
  --distribution-id E1XIDGUJGD9BU9 \
  --paths "/*"

Or use Hugo’s deployment feature:

[[deployment.targets]]
name = "production"
URL = "s3://your-bucket"
cloudFrontDistributionID = "E1XIDGUJGD9BU9"

Hugo will automatically invalidate the cache when deploying.

Asset Optimization and Caching

Hugo provides built-in asset processing that integrates with caching.

Resource Hashing

Hugo can automatically add content hashes to filenames:

{{ $css := resources.Get "css/main.css" | minify | fingerprint }}
<link rel="stylesheet" href="{{ $css.RelPermalink }}">

This generates filenames like main.min.abc123def456.css, enabling long-term caching since the hash changes when content changes.

Image Processing and Caching

Process images efficiently using Hugo’s built-in image processing. Hugo caches processed images, so resizing the same image multiple times only processes it once. For more advanced image handling, including OpenGraph image metadata generation, see our guide on Opengraph image metadata in Hugo static site generator:

{{ $image := resources.Get "images/photo.jpg" }}
{{ $resized := $image.Resize "800x600" }}
<img src="{{ $resized.RelPermalink }}" alt="Photo">

Asset Bundling

Bundle and minify assets:

{{ $css := slice 
    (resources.Get "css/reset.css")
    (resources.Get "css/main.css")
    (resources.Get "css/components.css")
  | resources.Concat "css/bundle.css"
  | minify
  | fingerprint
}}
<link rel="stylesheet" href="{{ $css.RelPermalink }}">

This creates a single cached, minified, and fingerprinted CSS file.

Service Worker Caching (Optional)

For advanced caching strategies, consider implementing service workers:

Basic Service Worker

// sw.js
const CACHE_NAME = 'hugo-site-v1';
const urlsToCache = [
  '/',
  '/css/main.css',
  '/js/main.js',
  '/images/logo.png'
];

self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then((cache) => cache.addAll(urlsToCache))
  );
});

self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request)
      .then((response) => response || fetch(event.request))
  );
});

Register Service Worker

<!-- In your Hugo template -->
<script>
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js');
}
</script>

Monitoring and Optimization

Build Time Monitoring

Track build performance:

# Time your builds
time hugo

# Use verbose output to see what's being processed
hugo --verbose

Cache Hit Rates

Monitor CDN cache hit rates through your CDN’s analytics dashboard. Aim for:

  • Static assets: >95% cache hit rate
  • HTML pages: 60-80% cache hit rate (depending on update frequency)

Performance Testing

Use tools like:

  • Lighthouse: Test caching effectiveness
  • WebPageTest: Analyze cache headers
  • GTmetrix: Monitor performance metrics

Best Practices Summary

  1. Enable Hugo’s build cache: Let Hugo cache processed resources
  2. Use incremental builds: Only rebuild what’s changed
  3. Configure CDN properly: Long TTLs for assets, shorter for HTML
  4. Set appropriate HTTP headers: Use immutable for hashed assets
  5. Fingerprint assets: Add content hashes to filenames
  6. Invalidate cache on deployments: Ensure users see updates
  7. Monitor performance: Track build times and cache hit rates
  8. Optimize images: Use Hugo’s image processing efficiently
  9. Bundle assets: Reduce HTTP requests with bundled CSS/JS
  10. Consider service workers: For offline-first or advanced caching needs

Conclusion

Effective caching strategies for Hugo sites involve multiple layers: build-time caching for faster development, CDN caching for global performance, and proper HTTP headers for browser caching. By implementing these strategies, you can achieve:

  • Faster builds: Incremental builds and build cache reduce build times
  • Better performance: CDN and browser caching improve load times
  • Reduced server load: Static assets cached at the edge
  • Improved user experience: Faster page loads and offline capabilities

Remember that caching is a balance between performance and freshness. Static assets can be cached aggressively, while HTML should have shorter cache times to ensure content updates are visible quickly.