• Skip to secondary menu
  • Skip to main content
  • Skip to primary sidebar
  • Home
  • Projects
  • Products
  • Themes
  • Tools
  • Request for Quote

Vengala Vinay

Having 9+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » Building a High-Availability, Cost-Optimized WooCommerce Stack on AWS

Building a High-Availability, Cost-Optimized WooCommerce Stack on AWS

Architectural Overview: HA & Cost-Optimized WooCommerce on AWS

This post details a robust, highly available, and cost-conscious WooCommerce deployment on Amazon Web Services (AWS). We’ll focus on leveraging managed services to reduce operational overhead and optimize spend, targeting CTOs and VPs of Engineering who need to balance performance, reliability, and budget.

Our stack prioritizes decoupling, scalability, and fault tolerance. Key components include:

  • Compute: AWS Elastic Kubernetes Service (EKS) for container orchestration, offering flexibility and scalability.
  • Database: Amazon Aurora PostgreSQL (Serverless v2) for its performance, scalability, and cost-effectiveness for variable workloads.
  • Caching: Amazon ElastiCache for Redis, crucial for WooCommerce performance.
  • Static Assets: Amazon S3 with CloudFront for efficient delivery of images, CSS, and JavaScript.
  • Load Balancing: AWS Application Load Balancer (ALB) integrated with EKS.
  • CDN: Amazon CloudFront for global content delivery.
  • Background Jobs: AWS SQS and AWS Batch for asynchronous processing.
  • Monitoring & Logging: Amazon CloudWatch and AWS X-Ray.

EKS Cluster Setup for WooCommerce

We’ll deploy WooCommerce as a set of Docker containers managed by Kubernetes. Using EKS abstracts away much of the Kubernetes control plane management, reducing operational burden. For cost optimization, we’ll utilize EC2 Spot Instances for worker nodes where appropriate, combined with On-Demand instances for critical workloads.

First, ensure you have the AWS CLI and kubectl configured. We’ll use eksctl for simplified EKS cluster creation.

Create a cluster configuration file (e.g., eks-config.yaml):

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: woocommerce-cluster
  region: us-east-1
  version: "1.28" # Specify your desired Kubernetes version

managedNodeGroups:
  - name: general-workers
    instanceType: m5.xlarge
    desiredCapacity: 3
    minSize: 1
    maxSize: 5
    # Use Spot Instances for cost savings on non-critical workloads
    spot: true
    labels: { role: "general" }
    tags:
      k8s.io/cluster-autoscaler/enabled: "true"
      k8s.io/cluster-autoscaler/woocommerce-cluster: owned

  - name: critical-workers
    instanceType: m5.2xlarge
    desiredCapacity: 2
    minSize: 1
    maxSize: 3
    # On-Demand instances for critical components like the database proxy or cache nodes
    spot: false
    labels: { role: "critical" }
    tags:
      k8s.io/cluster-autoscaler/enabled: "true"
      k8s.io/cluster-autoscaler/woocommerce-cluster: owned

addons:
  - name: vpc-cni
    version: latest
    resolveConflicts: overwrite
  - name: coredns
    version: latest
    resolveConflicts: overwrite
  - name: kube-proxy
    version: latest
    resolveConflicts: overwrite
  - name: aws-ebs-csi-driver
    version: latest
    resolveConflicts: overwrite

Create the EKS cluster:

eksctl create cluster -f eks-config.yaml

Once the cluster is provisioned, configure kubectl to connect to it:

aws eks update-kubeconfig --region us-east-1 --name woocommerce-cluster

Database: Amazon Aurora PostgreSQL (Serverless v2)

For WooCommerce, a performant and scalable database is paramount. Aurora PostgreSQL Serverless v2 offers automatic scaling based on demand, making it ideal for fluctuating e-commerce traffic and cost optimization. It scales compute and memory resources up and down within seconds.

When creating your Aurora cluster, configure the following:

  • Engine: PostgreSQL
  • Edition: Amazon Aurora
  • Capacity Type: Serverless v2
  • Minimum Aurora Capacity Units (ACUs): Set this based on your baseline load. For a new store, start low (e.g., 0.5 ACUs) and monitor.
  • Maximum Aurora Capacity Units (ACUs): Set this to handle peak traffic. This is a crucial cost control point. Monitor and adjust based on performance metrics.
  • Database Name: e.g., woocommerce_db
  • Master Username/Password: Securely store these credentials (e.g., using AWS Secrets Manager).
  • VPC: Ensure it’s the same VPC as your EKS cluster.
  • Security Groups: Allow inbound traffic from your EKS worker nodes’ security group on port 5432.

Cost Optimization Note: The key to cost-effectiveness with Serverless v2 is setting appropriate minimum and maximum ACU limits. Over-provisioning the maximum will lead to unnecessary costs. Regularly review CloudWatch metrics for Aurora Capacity Units consumed and adjust the maximum accordingly.

Caching with ElastiCache for Redis

WooCommerce heavily benefits from object caching. ElastiCache for Redis provides a low-latency, in-memory data store. For HA, we’ll deploy a Redis cluster with multiple nodes and replication.

Create an ElastiCache for Redis cluster:

  • Engine: Redis
  • Node Type: Choose based on your expected cache size and throughput (e.g., cache.m6g.large).
  • Number of Replicas: At least 1 for HA.
  • Shards: For larger datasets or higher throughput, consider sharding.
  • VPC: Same VPC as EKS.
  • Subnet Group: Ensure it spans multiple Availability Zones for HA.
  • Security Groups: Allow inbound traffic from EKS worker nodes on port 6379.

Cost Optimization Note: Use reserved instances for ElastiCache if your usage is predictable and long-term. For variable workloads, monitor cache hit/miss ratios and memory usage to right-size your nodes.

Static Assets: S3 and CloudFront

Offloading static assets (product images, themes, plugins) to S3 and serving them via CloudFront significantly reduces load on your application servers and improves global delivery speed.

1. Create an S3 Bucket:

aws s3 mb s3://your-unique-woocommerce-assets-bucket --region us-east-1

2. Configure CloudFront Distribution:

  • Origin Domain: Your S3 bucket’s website endpoint (if using static website hosting) or the bucket’s REST API endpoint.
  • Origin Access Identity (OAI): Create one and grant it read permissions to your S3 bucket. This restricts direct S3 access.
  • Cache Behavior: Configure TTLs, allowed HTTP methods, and query string forwarding.
  • Viewer Protocol Policy: Redirect HTTP to HTTPS.
  • Price Class: Choose based on your target audience’s geographic distribution.

3. Configure WooCommerce:

You’ll need to update your wp-config.php or use a plugin to point WordPress to your CloudFront URL for uploads and media library. For themes and plugins, you might need to manually adjust paths or use a CDN integration plugin.

Deploying WooCommerce on EKS

We’ll use Helm for deploying WooCommerce and its dependencies (like PHP-FPM, Nginx, and WordPress core) onto EKS. This provides a repeatable and manageable deployment process.

First, install Helm if you haven’t already:

curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

Add the Bitnami Helm repository (a common source for WordPress charts):

helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update

Create a Kubernetes namespace for your WooCommerce deployment:

kubectl create namespace woocommerce



Create a values.yaml file for your Helm deployment. This is where you'll configure connections to your managed services.

# values.yaml
replicaCount: 2 # Start with 2 replicas for HA

image:
  repository: wordpress
  tag: latest # Use a specific, tested version in production
  pullPolicy: IfNotPresent

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: true
  className: "nginx" # Assuming you've installed the Nginx Ingress Controller
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /
    # Add ALB annotations if using AWS ALB Ingress Controller
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-east-1:YOUR_ACCOUNT_ID:certificate/YOUR_CERT_ID # Replace with your ACM certificate ARN
    alb.ingress.kubernetes.io/ssl-redirect: "true"
  hosts:
    - host: your-domain.com # Replace with your domain
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: your-domain-tls # Kubernetes secret for TLS, managed by cert-manager or manually created
      hosts:
        - your-domain.com

wordpress:
  install: true
  # Database configuration - Use Kubernetes Secrets for sensitive data
  database:
    type: postgresql
    host: YOUR_AURORA_ENDPOINT.rds.amazonaws.com # Replace with your Aurora endpoint
    port: 5432
    user: woocommerce_user # Replace with your DB user
    password: YOUR_DB_PASSWORD # Store in Kubernetes Secret
    name: woocommerce_db # Replace with your DB name
  # Cache configuration - Use Kubernetes Secrets for sensitive data
  cache:
    enabled: true
    host: YOUR_REDIS_ENDPOINT # Replace with your ElastiCache endpoint
    port: 6379
    password: YOUR_REDIS_PASSWORD # Store in Kubernetes Secret (if password protected)

# Configure persistence if needed, but for stateless app servers, rely on external DB/Cache
# persistence:
#   enabled: false

# Resources for the WordPress pod
resources:
  requests:
    cpu: "500m"
    memory: "1Gi"
  limits:
    cpu: "1000m"
    memory: "2Gi"

# Configure WordPress to use Redis Object Cache plugin
extraEnvVars:
  - name: WORDPRESS_REDIS_HOST
    value: "YOUR_REDIS_ENDPOINT" # Replace with your ElastiCache endpoint
  - name: WORDPRESS_REDIS_PORT
    value: "6379"
  # Add WORDPRESS_REDIS_PASSWORD if your Redis instance requires authentication

# Mount a ConfigMap for wp-config.php to inject Redis Object Cache settings
# Or use a dedicated plugin deployment
extraVolumeMounts:
  - name: wp-config-volume
    mountPath: /var/www/html/wp-config.php
    subPath: wp-config.php

extraVolumes:
  - name: wp-config-volume
    configMap:
      name: woocommerce-wp-config

# Configure PHP-FPM settings if needed
php:
  memoryLimit: "512m"
  maxChildren: 10 # Adjust based on worker node CPU/memory

# Configure Nginx settings if needed
nginx:
  enabled: true
  workerProcesses: 2
  # Adjust worker_connections based on available resources
  workerConnections: 1024

# Enable persistent storage for uploads if not using S3 directly for uploads
# This is less common with S3/CloudFront setup but can be useful for initial setup
# or specific workflows.
# persistence:
#   enabled: true
#   storageClass: "gp2" # Or your preferred StorageClass
#   size: 10Gi

# Configure WordPress to use S3 for uploads
# This typically requires a plugin like "WP Offload Media Lite" or "WP Offload Media"
# You would configure this plugin via its own settings or environment variables if possible.
# For simplicity, we'll assume a plugin is installed and configured separately.
# Example environment variables for a hypothetical S3 offload plugin:
# extraEnvVars:
#   - name: WP_S3_BUCKET
#     value: "your-unique-woocommerce-assets-bucket"
#   - name: WP_S3_REGION
#     value: "us-east-1"
#   - name: WP_S3_KEY
#     valueFrom:
#       secretKeyRef:
#         name: aws-credentials
#         key: aws_access_key_id
#   - name: WP_S3_SECRET
#     valueFrom:
#       secretKeyRef:
#         name: aws-credentials
#         key: aws_secret_access_key

Important Security Note: Never hardcode database or cache passwords in your Helm values. Use Kubernetes Secrets and reference them using valueFrom.secretKeyRef. You'll need to create these secrets beforehand.

Create a Kubernetes Secret for your database password:

kubectl create secret generic woocommerce-secrets \
  --namespace woocommerce \
  --from-literal=WORDPRESS_DB_PASSWORD='YOUR_DB_PASSWORD' \
  --from-literal=WORDPRESS_REDIS_PASSWORD='YOUR_REDIS_PASSWORD' # If Redis is password protected

And a ConfigMap for wp-config.php to enable Redis Object Cache:

<?php
/**
 * The base configuration for WordPress
 *
 * The wp-config.php creation script uses this file. You will also use
 * this file to save the credentials you received from your host,
 * the table prefix, and other essential settings.
 *
 * @link https://wordpress.org/documentation/article/editing-wp-config-php/
 *
 * @package WordPress
 */

// ** Database settings - You can get this info from your hosting provider ** //
/** The name of the database for WordPress */
define( 'DB_NAME', getenv('WORDPRESS_DB_NAME') ?: 'woocommerce_db' );

/** Database hostname */
define( 'DB_HOST', getenv('WORDPRESS_DB_HOST') ?: 'YOUR_AURORA_ENDPOINT.rds.amazonaws.com' );

/** Database username */
define( 'DB_USER', getenv('WORDPRESS_DB_USER') ?: 'woocommerce_user' );

/** Database password */
define( 'DB_PASSWORD', getenv('WORDPRESS_DB_PASSWORD') ?: '' );

/** Database charset to use in creating database tables. */
define( 'DB_CHARSET', 'utf8' );

/** The database for WordPress */
define( 'DB_COLLATE', '' );

/**#@-*/

/**
 * WordPress Localized Language, and Right to Left Quiet.
 *
 * For multilingual blogs, use code like 'es' for Spanish.
 *
 * @link https://wordpress.org/documentation/article/editing-wp-config-php/#language
 */
define( 'WPLANG', '' );

/**
 * For developers: WordPress debugging mode.
 *
 * Change this to true to enable the display of notices during development.
 * It is recommended that plugin and theme developers use WP_DEBUG_LOG
 * in their development environments.
 */
define( 'WP_DEBUG', false );
if ( WP_DEBUG ) {
    define( 'WP_DEBUG_LOG', true );
    define( 'WP_DEBUG_DISPLAY', false );
    @ini_set( 'display_errors', 0 );
}

/* That's all, stop editing! Happy publishing. */

/**
 * Redis Object Cache settings
 */
define( 'WP_REDIS_CLIENT', 'phpredis' );
define( 'WP_REDIS_HOST', getenv('WORDPRESS_REDIS_HOST') ?: 'YOUR_REDIS_ENDPOINT' );
define( 'WP_REDIS_PORT', getenv('WORDPRESS_REDIS_PORT') ?: 6379 );
define( 'WP_REDIS_PASSWORD', getenv('WORDPRESS_REDIS_PASSWORD') ?: '' );
define( 'WP_REDIS_TIMEOUT', 1 );
define( 'WP_REDIS_READ_TIMEOUT', 1 );
define( 'WP_REDIS_DATABASE', 0 );
define( 'WP_REDIS_MAXCLIENTS', 256 );
define( 'WP_REDIS_PROTOCOL', 'tcp' );
define( 'WP_REDIS_SSL', false ); // Set to true if your Redis requires SSL

/** WordPress absolute path to the WordPress directory. */
if ( ! defined( 'ABSPATH' ) ) {
    define( 'ABSPATH', __DIR__ . '/' );
}

/** Sets up WordPress vars and included files. */
require_once ABSPATH . 'wp-settings.php';
kubectl create configmap woocommerce-wp-config \
  --namespace woocommerce \
  --from-file=wp-config.php=./wp-config.php

Now, deploy WooCommerce using Helm:

helm install woocommerce bitnami/wordpress \
  --namespace woocommerce \
  -f values.yaml

After deployment, you'll need to install the "Redis Object Cache" plugin within WordPress and activate it. You might also need to install and configure a plugin for S3 media offloading (e.g., "WP Offload Media").

Ingress and Load Balancing

We'll use the AWS Application Load Balancer (ALB) with the AWS Load Balancer Controller for Kubernetes. This allows the ALB to automatically provision and manage based on Kubernetes Ingress resources.

1. Install the AWS Load Balancer Controller: Follow the official AWS documentation for installing the controller into your EKS cluster. This typically involves applying a Kubernetes manifest.

# Example command, refer to AWS docs for the latest version and IAM policy
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.7.1/docs/install/iam_policy.json
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.7.1/docs/install/rbac.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.7.1/docs/install/controller.yaml

2. Configure Ingress: The values.yaml file above includes basic Ingress configuration. Ensure your className and annotations are correct for the AWS ALB Ingress Controller. You'll need to replace placeholders for your domain and ACM certificate ARN.

3. DNS Configuration: Point your domain's A record (or CNAME) to the DNS name of the provisioned ALB. You can find this by running kubectl get ingress -n woocommerce and looking at the ADDRESS field.

Background Jobs and Asynchronous Processing

WooCommerce often involves background tasks like order processing, email notifications, and cron jobs. Offloading these from the main web application improves responsiveness and scalability.

1. AWS SQS for Queues: Use SQS to decouple tasks. For example, when an order is placed, push a message to an SQS queue for "order processing."

2. AWS Batch or Kubernetes Jobs: Create worker services (either as Kubernetes Jobs/CronJobs or AWS Batch jobs) that poll the SQS queue and process messages. This allows you to scale these workers independently.

Cost Optimization: SQS is very cost-effective for message queuing. AWS Batch can be cost-optimized by leveraging Spot Instances for compute. For simple cron jobs, Kubernetes CronJobs are efficient.

Monitoring, Logging, and Cost Management

Comprehensive monitoring is essential for performance and cost control.

  • CloudWatch: Collect logs from EKS pods, ALB, Aurora, and ElastiCache. Set up Alarms for key metrics (CPU utilization, memory, error rates, database connections, cache hit ratios).
  • AWS X-Ray: Integrate X-Ray for distributed tracing to identify performance bottlenecks across services.
  • Kubernetes Metrics: Use tools like Prometheus and Grafana (deployed within EKS) or CloudWatch Container Insights for detailed cluster and pod performance.
  • Cost Explorer & Budgets: Regularly review AWS Cost Explorer to understand spending patterns. Set up AWS Budgets to receive alerts when costs exceed predefined thresholds. Tag all resources meticulously for accurate cost allocation.

Cost Optimization Strategy:

  • Right-size Instances: Continuously monitor and adjust EC2 instance types for worker nodes and ElastiCache nodes.
  • Utilize Spot Instances: For non-critical workloads (e.g., general worker nodes, batch processing), leverage Spot Instances for significant cost savings.
  • Aurora Serverless v2 Tuning: Carefully set ACU limits for Aurora Serverless v2.
  • S3 Lifecycle Policies: Move older, less frequently accessed data in S3 to cheaper storage tiers (e.g., S3 Infrequent Access).
  • CDN Caching: Maximize cache hit ratios on CloudFront by setting appropriate TTLs.
  • Database Connection Pooling: Implement connection pooling on the application side to reduce the load on Aurora.
  • Code Optimization: Profile and optimize slow database queries and inefficient PHP code.

By combining managed AWS services with a well-architected Kubernetes deployment, you can achieve a highly available, scalable, and cost-optimized WooCommerce platform.

Primary Sidebar

A little about the Author

Having 9+ Years of Experience in Software Development.
Expertised in Php Development, WordPress Custom Theme Development (From scratch using underscores or Genesis Framework or using any blank theme or Premium Theme), Custom Plugin Development. Hands on Experience on 3rd Party Php Extension like Chilkat, nSoftware.

Recent Posts

  • Step-by-Step: Diagnosing thread pools deadlock during concurrent ActiveRecord transaction processing on Linode Servers
  • Securing Your E-commerce APIs: Preventing SQL Injection (SQLi) in customized checkout queries in WooCommerce Implementations
  • Disaster Recovery 101: Architecting Auto-Failovers for MySQL and Ruby Deployments on Linode
  • High-Throughput Caching Strategies: Scaling MySQL for Perl Application APIs
  • Disaster Recovery 101: Architecting Auto-Failovers for DynamoDB and Laravel Deployments on DigitalOcean

Copyright © 2026 · Vinay Vengala