Back to articles
Technology Insight

Building a High Availability (HA) Architecture for Headless CMS Strapi on 3 Hetzner VPS Nodes with HAProxy

May 30, 2026

Introduction: The Necessity of High Availability for Enterprise Content Delivery

In modern web development, the headless content management system (CMS) has transitioned from a flexible alternative to an enterprise standard. Strapi, as a leading open-source headless CMS, powers critical digital experiences across e-commerce platforms, corporate applications, and content-heavy portals. However, deploying Strapi on a single server introduces a single point of failure (SPOF). If that server experiences hardware degradation, network anomalies, or high traffic spikes, your entire digital ecosystem halts.

To guarantee maximum uptime and seamless user experiences, engineering teams must implement a High Availability (HA) architecture. High availability ensures that if one component fails, redundant systems automatically take over without disrupting the end-user. This technical guide provides an exhaustive blueprint for building a resilient, production-ready HA cluster for Strapi utilizing three cost-effective Hetzner Cloud VPS nodes and HAProxy as the intelligent load-balancing tier.

---

1. The Architectural Blueprint

A truly resilient HA architecture requires decoupling the application tier from stateful data components. If application nodes store media locally or run independent databases, synchronization breaks. Our architecture isolates the presentation and business logic into stateless application nodes, while centralizing database transactions and asset storage.

Component Breakdown

  • Load Balancing Tier (1x Hetzner VPS or Hetzner Load Balancer): Runs HAProxy to intercept incoming traffic, monitor backend health, and distribute requests intelligently across the Strapi nodes.
  • Application Tier (3x Hetzner CX22/CPX22 VPS): Three identical nodes running Strapi instances concurrently. They pull content from a shared database and manage assets through shared object storage.
  • Database Tier (Managed Database or Isolated Cluster): A centralized, highly available PostgreSQL database instance. For true production environments, utilizing Hetzner’s Managed Database service or a replicated PostgreSQL cluster (via Patroni or PgBouncer) is strongly recommended.
  • Storage Tier (Shared Object Storage): Standard local storage will not work in a multi-node Strapi setup because an asset uploaded to Node 1 would be missing on Nodes 2 and 3. We leverage AWS S3, MinIO, or Hetzner Storage Boxes combined with the Strapi S3 provider plugin to keep media files accessible universally.
---

2. Prerequisites and Environment Preparation

Before executing configuration scripts, ensure your infrastructure meets the following baseline requirements:

  • Three Hetzner Cloud VPS instances (e.g., CPX22 with AMD EPYC processors, 4GB RAM, running Ubuntu 24.04 LTS).
  • A separate server or cloud-native service for PostgreSQL.
  • An S3-compatible bucket (e.g., AWS S3, DigitalOcean Spaces, or self-hosted MinIO).
  • A dedicated VPS or Hetzner Load Balancer for HAProxy.
  • A domain name pointing to your load balancer's public IP address.
  • Node.js (v18 or v20 LTS) and npm/yarn installed across all application nodes.
Important Note on Network Security: Always enable Hetzner Private Networks (vSwitch) to isolate inter-node communication (Strapi to Database, HAProxy to Strapi). This drastically reduces the attack surface by keeping internal traffic off the public internet.
---

3. Step-by-Step Deployment Guide

Step 3.1: Configuring the Centralized Database & Shared Storage

First, initialize your highly available PostgreSQL instance. Ensure that your pg_hba.conf file is explicitly configured to accept incoming connections from the private IP ranges of your three Strapi VPS nodes. Create a dedicated user and database for your Strapi installation:

CREATE USER strapi_user WITH PASSWORD 'YourSecurePasswordHere';
CREATE DATABASE strapi_prod;
GRANT ALL PRIVILEGES ON DATABASE strapi_prod TO strapi_user;

Next, configure your S3-compatible storage bucket. Note down your Access Key, Secret Key, Bucket Name, and Endpoint URL. These variables will ensure that whenever a content editor uploads an image or video, it is securely offloaded to the cloud bucket instead of the local node's file system.

Step 3.2: Setting Up the Stateless Strapi Instances

On all three Strapi VPS nodes, clone your project codebase. To maintain absolute environment consistency, configure your config/plugins.js file to utilize the S3 provider plugin:

module.exports = ({ env }) => ({
  upload: {
    config: {
      provider: 'aws-s3',
      providerOptions: {
        s3Options: {
          accessKeyId: env('AWS_ACCESS_KEY_ID'),
          secretAccessKey: env('AWS_ACCESS_SECRET'),
          region: env('AWS_REGION'),
          endpoint: env('AWS_ENDPOINT'),
          forcePathStyle: true,
        },
        params: {
          Bucket: env('AWS_BUCKET'),
        },
      },
    },
  },
});

Create identical .env files across all three nodes. Crucially, ensure that the APP_KEYS, API_TOKEN_SALT, ADMIN_JWT_SECRET, and JWT_SECRET values are exactly identical. If these cryptographic keys differ between servers, user sessions and API authentication tokens will fail when HAProxy routes a user from Node 1 to Node 2.

Launch Strapi using a process manager like PM2 to guarantee automatic restarts upon failure or server reboots:

pm2 start server.js --name "strapi-app"
pm2 save
pm2 startup

Step 3.3: Configuring HAProxy for Load Balancing and Health Checks

SSH into your dedicated load balancer VPS and install HAProxy: sudo apt update && sudo apt install haproxy -y. Open the primary configuration file located at /etc/haproxy/haproxy.cfg and append the following production configuration block:

frontend strapi_frontend
    bind *:80
    bind *:443 ssl crt /etc/ssl/certs/your_domain.pem
    mode http
    option forwardfor
    http-request set-header X-Forwarded-Proto https if { ssl_fc }
    default_backend strapi_backend

backend strapi_backend
    mode http
    balance roundrobin
    option httpchk GET /_health
    http-check expect status 200
    cookie STRAPI_NODE insert indirect nocache
    server strapi-node-1 10.0.0.11:1337 check cookie strapi-node-1
    server strapi-node-2 10.0.0.12:1337 check cookie strapi-node-2
    server strapi-node-3 10.0.0.13:1337 check cookie strapi-node-3

listen stats
    bind *:9000
    mode http
    stats enable
    stats uri /
    stats auth admin:YourSecureStatsPassword

Validate the syntax and restart the service to apply changes:

haproxy -c -f /etc/haproxy/haproxy.cfg
sudo systemctl restart haproxy
---

4. Deep Dive: Managing Stateful Operations in a Stateless Cluster

Running multi-node configurations introduces unique synchronization challenges that must be systematically managed:

The Role of Sticky Sessions

While the Strapi Content Delivery API (GET requests) is entirely stateless and can utilize pure roundrobin balancing, the Strapi Admin Panel (the dashboard used by content authors) relies heavily on active user sessions. In our HAProxy configuration, we implemented cookie STRAPI_NODE insert indirect nocache. This establishes sticky sessions, ensuring that an editor working inside the admin dashboard remains pinned to the exact same backend server for the duration of their session. This prevents unexpected logouts and form-submission conflicts.

Handling Scheduled Tasks and Cron Jobs

If you enable built-in cron jobs within Strapi across a 3-node cluster, those tasks will execute three times simultaneously. To avoid duplicated operations (such as sending multiple newsletter emails or publishing repetitive logs), you must disable local crons in your environment variables on two nodes, leaving only one dedicated node to process automation. Alternatively, offload task scheduling to an external system like a centralized server or GitHub Actions that triggers Strapi webhooks sequentially.

---

5. Performance Optimization and Maintenance

An HA cluster is only as good as its underlying operational optimization. Implement these performance enhancements to maximize the efficiency of your Hetzner nodes:

  • Enable Redis Caching: Integrate a Redis cluster into Strapi via community caching plugins. This caches frequent API payloads globally, reducing repetitive and resource-intensive queries to your database tier.
  • Automated Rolling Deployments: When deploying code updates, do not take all three nodes offline at once. Implement a rolling update strategy: take Node 1 offline, pull new code, restart via PM2, verify its health status via HAProxy, and then proceed sequentially to Node 2 and Node 3. This guarantees continuous uptime during production deployments.
  • Proactive Monitoring: Utilize HAProxy's built-in stats dashboard (on port 9000) to view real-time traffic distributions, active connections, and node response times. Combine this with Prometheus and Grafana to track resource metrics across all Hetzner nodes.
---

Conclusion

By implementing this 3-node HA architecture for Strapi on Hetzner Cloud, you successfully eliminate single points of failure, ensuring your content infrastructure remains highly performant and accessible under extreme demands. Decoupling storage via S3, securing transactions with a centralized database, and distributing traffic via HAProxy yields an enterprise-grade infrastructure built on cost-effective, high-performance open-source tools. Monitor your cluster health consistently, automate your deployments, and your digital experiences will confidently scale alongside your business growth.

Building a High Availability (HA) Architecture for Headless CMS Strapi on 3 Hetzner VPS Nodes with HAProxy | DPTCloud