{"id":2,"date":"2026-09-27T13:25:27","date_gmt":"2026-09-27T13:25:27","guid":{"rendered":"http:\/\/3.235.167.136\/?page_id=2"},"modified":"2026-09-28T09:28:56","modified_gmt":"2026-09-28T09:28:56","slug":"sample-page","status":"publish","type":"page","link":"https:\/\/blog.bassemriad.com\/index.php\/sample-page\/","title":{"rendered":"Building a Three-Tier WordPress Site on AWS"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">For my second bootcamp project, I moved past static hosting and built a real three-tier architecture from scratch with CloudFormation \u2014 a load-balanced, auto-scaling WordPress site backed by a private database and shared storage. Here&#8217;s what I actually built, and what I learned putting it together.<\/p>\n\n\n\n<p class=\"is-style-text-subtitle is-style-text-subtitle--1 wp-block-paragraph\"><strong>The problem with one server<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A single EC2 instance running WordPress works fine until it doesn&#8217;t \u2014 it can&#8217;t handle a traffic spike, and if it goes down, so does the whole site. The fix is to split the system into three independent tiers that can each fail or scale on their own.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"471\" src=\"https:\/\/blog.bassemriad.com\/wp-content\/uploads\/2026\/09\/blog.bassemriad-1024x471.png\" alt=\"\" class=\"wp-image-8\" srcset=\"https:\/\/blog.bassemriad.com\/wp-content\/uploads\/2026\/09\/blog.bassemriad-1024x471.png 1024w, https:\/\/blog.bassemriad.com\/wp-content\/uploads\/2026\/09\/blog.bassemriad-300x138.png 300w, https:\/\/blog.bassemriad.com\/wp-content\/uploads\/2026\/09\/blog.bassemriad-766x352.png 766w, https:\/\/blog.bassemriad.com\/wp-content\/uploads\/2026\/09\/blog.bassemriad-1536x706.png 1536w, https:\/\/blog.bassemriad.com\/wp-content\/uploads\/2026\/09\/blog.bassemriad.png 1906w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"is-style-text-subtitle is-style-text-subtitle--2 wp-block-paragraph\"><strong>The web tier<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">An Application Load Balancer sits in front of an Auto Scaling Group of EC2 instances, each running Apache and PHP. The ASG watches CPU usage and launches a new instance automatically once it crosses 70% \u2014 the ALB starts sending it traffic the moment it passes a health check. No manual intervention, no downtime.<\/p>\n\n\n\n<p class=\"is-style-text-subtitle is-style-text-subtitle--3 wp-block-paragraph\"><strong>The database tier<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">MySQL runs on RDS, inside private subnets with no route to the internet at all \u2014 it&#8217;s not reachable from outside the VPC no matter what. The master password is generated and stored by Secrets Manager, never written into any file or typed by hand. Later, I added a read replica and wired it in with HyperDB, so read-heavy traffic (most of what a blog does) can be split off from writes.<\/p>\n\n\n\n<p class=\"is-style-text-subtitle is-style-text-subtitle--4 wp-block-paragraph\"><strong>The storage tier<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Uploaded media doesn&#8217;t live on any one instance \u2014 it&#8217;s stored on EFS, mounted at <code>wp-content\/uploads<\/code> on every server at once. That means an image uploaded through one instance is instantly visible from all the others, and it survives an instance being replaced entirely.<\/p>\n\n\n\n<p class=\"is-style-text-subtitle is-style-text-subtitle--5 wp-block-paragraph\"><strong>Making it faster: CloudFront and Redis<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Two optimizations on top of the base setup: CloudFront now sits in front of the load balancer, caching static assets like images at edge locations worldwide \u2014 a second request for the same image comes back from the edge, not from EFS. And Redis (via ElastiCache) caches WordPress&#8217;s database queries in memory, so PHP doesn&#8217;t have to round-trip to MySQL on every single page load.<\/p>\n\n\n\n<p class=\"is-style-text-subtitle is-style-text-subtitle--6 wp-block-paragraph\"><strong>What I&#8217;d tell past me<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The trickiest bug wasn&#8217;t infrastructure \u2014 it was WordPress not realizing it was being served over HTTPS, because CloudFront terminates TLS at the edge but talks to the load balancer over plain HTTP internally. That one cost me a redirect loop on the admin dashboard until I found it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Everything here deploys with a single CloudFormation stack, and redeploys automatically on every push via GitHub Actions, authenticating with a short-lived OIDC role instead of stored AWS keys.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>For my second bootcamp project, I moved past static hosting and built a real three-tier architecture from scratch with CloudFormation \u2014 a load-balanced, auto-scaling WordPress site backed by a private database and shared storage. Here&#8217;s what I actually built, and what I learned putting it together. The problem with one server A single EC2 instance [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"open","template":"","meta":{"footnotes":""},"class_list":["post-2","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/blog.bassemriad.com\/index.php\/wp-json\/wp\/v2\/pages\/2","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.bassemriad.com\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/blog.bassemriad.com\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/blog.bassemriad.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.bassemriad.com\/index.php\/wp-json\/wp\/v2\/comments?post=2"}],"version-history":[{"count":2,"href":"https:\/\/blog.bassemriad.com\/index.php\/wp-json\/wp\/v2\/pages\/2\/revisions"}],"predecessor-version":[{"id":9,"href":"https:\/\/blog.bassemriad.com\/index.php\/wp-json\/wp\/v2\/pages\/2\/revisions\/9"}],"wp:attachment":[{"href":"https:\/\/blog.bassemriad.com\/index.php\/wp-json\/wp\/v2\/media?parent=2"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}