← Back to the reel Sep 2026 – now

Fifty sites, one tower

Migrating 50+ WordPress sites into one code-based, multi-tenant platform with zero-downtime releases.

Client
Spendtime (PT Spend Group International)
Role
Head of IT · architect · hands-on lead for 2 developers
  • 50+ sites consolidating
  • 3 deployables, one monorepo
  • 0 downtime, by design

The problem

The company ran more than fifty WordPress sites. Every one had its own plugins, its own update schedule and its own way of breaking. SEO settings, ad pixels and SMTP were configured by hand, site by site.

Every new site multiplied the maintenance. Every plugin update was a small gamble.

The moves

  1. One monorepo, three deployables

    A public web app that serves each tenant on its own domain, an admin dashboard (blog CMS, SEO metadata, Meta and Google Ads settings, SMTP), and background workers, all sharing types and data access.

  2. Workers split by how they hurt the server

    A fast worker (low memory, high concurrency) for analytics, email, scheduled publishing, sitemaps and IndexNow. A heavy worker (more memory, low concurrency) for SEO crawls, AI SEO suggestions, media processing and Search Console sync. One noisy job can no longer starve the rest.

  3. Releases nobody has to stay up for

    Docker images built in GitHub Actions, deployed through Coolify and Traefik with readiness probes. Database changes follow expand → backfill → contract, and a failed smoke test rolls the release back automatically.

  4. Shared data, kept in its lane

    One PostgreSQL database scoped by tenant_id behind PgBouncer, a dedicated Redis, and Garage for S3-compatible object storage.

The outcome

A platform where adding a site is configuration, not a new server.

Two junior developers working inside a clear architecture, with code review and coaching instead of guesswork.

  • TypeScript
  • Turborepo
  • PostgreSQL
  • PgBouncer
  • Redis
  • BullMQ
  • Garage S3
  • Docker
  • GitHub Actions
  • Coolify
  • Traefik

Note: In progress. Details are kept general on purpose.