Felix Dziekan

Typo3-caching mit Varnish

Gepostet von: Felix Dziekan in: Blog am Apr 26, 2026

You've got your TYPO3 running, your web server configured, and your website is live. But as traffic grows, you start thinking about performance. Do you just throw more server power at it? No. You build a proper caching stack in front of it.

In this post I'll walk you through how to set up a load balancer, cache layer and web server together with TYPO3 in production — using simplified and safe example configurations.

The Architecture

Before we look at any config, let's understand the full request flow:

Browser → Load Balancer → Cache Layer → Web Server → PHP-FPM → TYPO3

Each layer has one job:

  • Load Balancer — handles SSL termination and routes traffic
  • Cache Layer — caches full HTTP responses in memory
  • Web Server — only gets hit on a cache miss
  • TYPO3 — only processes requests when no cached response exists

The goal is simple: make sure TYPO3 does as little work as possible.

Load Balancer — The Front Door

The load balancer sits at the very front of the stack. It handles SSL termination and decides — based on hostname and path — where each request goes. Not everything should be cached. The TYPO3 backend must always bypass the cache.

 

frontend http-in
  bind *:80
  bind *:443 ssl crt /path/to/certs/

  http-request set-header X-Forwarded-Port %[dst_port]
  http-request add-header X-Forwarded-Proto https if { ssl_fc }

  acl site hdr_end(host) -i example.com
  acl admin_path path_beg -i /typo3

  use_backend backend_admin if site admin_path
  use_backend cache_layer if site

backend backend_admin
  server app_backend:80
  http-request auth unless { http_auth(admin-auth-list) }

backend app_backend
  server app_backend:80

backend cache_layer
  server cache_service:6081

 

Always route your TYPO3 admin path directly to the backend and bypass the cache entirely.

Cache Layer — Configuration

The cache layer handles HTTP caching and ensures that repeated requests never reach TYPO3.

 

vcl 4.1;

backend default {
    .host = "app_backend";
    .port = "80";
}

sub vcl_recv {
    if (req.method != "GET" && req.method != "HEAD") {
        return (pass);
    }

    if (req.http.Cookie ~ "fe_typo_user") {
        return (pass);
    }

    unset req.http.Cookie;

    return (hash);
}

sub vcl_backend_response {
    unset beresp.http.Set-Cookie;
    set beresp.ttl = 30d;

    return (deliver);
}

sub vcl_deliver {
    if (obj.hits > 0) {
        set resp.http.X-Cache = "HIT";
    } else {
        set resp.http.X-Cache = "MISS";
    }
}

 

Only GET and HEAD are cached. All other requests go directly to TYPO3.

Logged-in users bypass the cache. This prevents personalised content from being cached and served to other users.

Long TTLs are intentional. Cache invalidation ensures fresh content instead of relying on short cache times.

TYPO3 Reverse Proxy Configuration

Add the following to your configuration:

 

$GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxyIP'] = 'cache-layer-ip';
$GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxyHeaderMultiValue'] = 'first';
$GLOBALS['TYPO3_CONF_VARS']['SYS']['trustedHostsPattern'] = '.*';

 

This ensures TYPO3 correctly resolves client IPs and protocol headers.

Cache Invalidation

To keep cached content fresh, use an extension that triggers cache invalidation when content changes:

 

composer require opsone-ch/varnish

 

This ensures:

  • Cache is cleared when content is updated
  • Fresh content is served immediately after changes
  • Long cache lifetimes remain safe

Choose One Caching Strategy

Do not combine multiple full-page caching systems.

  • Avoid running two caching layers in parallel
  • Prevent conflicting cache states
  • Keep cache invalidation simple and predictable

Pick one caching strategy and stick to it. Simplicity is key to reliable performance.

Bye Bye

Well that's it from my side for today.
Have a good one!

Hire Me: From small to big business

Whether you're a nimble startup needing a consultant who can guide you through the complex IT-Jungle or a large-scale international company seeking a skilled team player, I'm here to help.