Static to Production

Chapter 2: Plan Before You Build

2,902 words

General
Report

Chapter 2:
Plan Before You Build

Context

Most infrastructure problems that look like technical problems are actually planning problems. A misconfigured security group that blocks traffic, a missing IAM permission that fails silently, a CloudFront distribution pointed at the wrong origin: these are not hard bugs to fix once you find them. They are hard to find because the person who built the system did not have a clear picture of it before they started.

The cost of discovering a gap on paper is nothing. The cost of discovering it after you have built three dependent resources on top of it is significant. You have to trace backward through what you built, figure out where the assumption broke down, fix it, and then verify the fix did not break anything downstream.

This chapter walks through the planning sequence for this project and introduces the architecture diagram of the full system. You will not draw it from scratch. You will read it, trace both paths through it, and find what it leaves out. Reading a diagram critically is a skill you will use far more often than drawing one.

Concept: Drawing Before Building

Before any sysadmin provisioned a server in a physical data center, they had a network diagram. Not necessarily a formal one produced in a professional tool. Sometimes a whiteboard sketch. Sometimes a rough drawing on paper. The discipline of drawing before building is as old as the field itself, and for good reason.

A physical network diagram shows what equipment exists, where it sits, and how it connects. It shows which interfaces are public-facing and which are internal. A rack diagram shows what occupies each rack unit and how cables route between devices.

These diagrams serve two purposes. The first is planning: you identify what you need to build before you build it, and gaps in the diagram reveal components you forgot to account for. The second is communication: the diagram is a reference any engineer can read without digging through configuration files.

Cloud infrastructure is the same discipline. The resources live in AWS data centers instead of yours, and the diagrams use different visual conventions, but the questions are identical. What components exist? Where do they sit? How do they connect? What is public-facing and what is not?

The Planning Sequence

Every build in this book follows the same five-step sequence before any tooling is touched. This chapter walks through all five for this project. In later chapters, you will move through them faster as the habit becomes familiar.

Step 1: Identify exactly what is being built.

A static website, deployed automatically from a Git repository, served globally over HTTPS, with no stored AWS credentials anywhere in the pipeline.

Step 2: List the actual requirements.

Security: no long-lived AWS credentials stored in GitHub or anywhere else. Least-privilege access for the deployment identity. No unnecessary public exposure of AWS resources.

Reliability: the site must remain available to visitors even if one AWS data center has a problem. Content delivery should not bottleneck on a single origin location.

Cost: must run within the AWS free tier for a new account, with costs under $1/month thereafter at low traffic.

Maintainability: all infrastructure must be defined in code so it can be reproduced, reviewed, and version-controlled. Manual configuration in the AWS console is not acceptable for anything that needs to persist.

Operational complexity: the deployment must be fully automated. A commit to main should produce a live update with no manual steps.

Step 3: Select the simplest option that meets those requirements.

S3 for file storage. CloudFront for global delivery and HTTPS. GitHub Actions for CI/CD. Terraform for infrastructure as code. OIDC for credential-free authentication between GitHub and AWS.

Why not EC2? A running server to serve static files adds cost, patching overhead, and availability risk for no benefit. S3 and CloudFront together deliver the same result with none of that overhead.

Why not AWS CodePipeline? GitHub Actions is where the repository already lives. Keeping the pipeline in GitHub means the deployment configuration is version-controlled alongside the code it deploys, without maintaining a separate pipeline configuration inside AWS.

Why not CloudFormation? Terraform is provider-agnostic and the state management model is more flexible for future work. The author's choice here is a legitimate engineering preference, not a universal truth. CloudFormation works equally well for this project.

Step 4: Plan the infrastructure before opening any tooling.

This is what the rest of this chapter does, using the architecture diagram for this project.

Step 5: Build incrementally.

You will build one resource at a time across the chapters that follow. Each chapter adds a layer to the system and verifies it before the next layer goes on top.

AWS Mapping: How to Read an AWS Architecture Diagram

Physical network diagrams use a standardized visual language. Routers look one way, switches look another, servers look a third way. An engineer who knows that convention can read any diagram produced anywhere.

AWS architecture diagrams work the same way. AWS publishes an official icon set for every service in its catalog, and diagramming tools such as draw.io include these icons built in. When you see the CloudFront icon next to an S3 bucket icon with an arrow between them, you understand the relationship immediately without reading any text. The diagram in this chapter uses the official icons. Labeled boxes would carry the same information, and many engineers start with plain boxes and add icons later. The point of a diagram is clarity, not presentation.

Four conventions make a diagram readable, and the diagram in this chapter uses all of them.

Icons identify services. Each service has its own icon, and each icon has a text label underneath. Never rely on the icon alone. A label costs nothing and removes ambiguity for the reader who has not memorized the icon set.

Boundaries show scope. A dashed box marks a boundary, and the label in its corner says what the boundary is. In AWS diagrams the most common boundaries are the AWS account, the region, and the network. This project's diagram draws one: a region box labeled us-east-1. That box is a statement about the services inside it and, just as importantly, the services outside it.

Some AWS services live inside a single region. S3 is one of them: a bucket is created in a specific region and its objects are stored there. Other services are global and do not belong to any one region. IAM is global. CloudFront is global: a distribution serves visitors from edge locations around the world, not from a single region. This is why, in the diagram, only S3 sits inside the us-east-1 box while CloudFront, the IAM role, and the IAM OIDC provider sit outside it. Placing a global service inside a region box would be an error, because it would suggest the service is tied to a location it is not tied to.

Arrows show the direction of flow, and you must know which flow. An arrow can mean a request, a data transfer, a trust relationship, or a trigger. Diagrams rarely say which. You have to decide from context, and you should decide before you trust the picture. This point matters enough that the next section returns to it.

A diagram is not an inventory. An architecture diagram shows the main components of the system and how they relate. It is not a list of every resource Terraform creates. Terraform state storage, for instance, is infrastructure that supports the tooling. It is not part of the system the diagram communicates. It is left off, and so are the bucket policy, the public access block, and the other supporting resources you will meet in Chapters 4 to 6.

The System You Are Diagramming

The diagram covers the runtime system: what serves the site to visitors, and what deploys updates to it. Here is the architecture diagram for this project.

Architecture of the static site pipeline. Global services (CloudFront, IAM) sit outside the regional boundary.

The diagram contains eight labeled components. Read them in two groups.

The deployment side:

Developer: the person who edits the site files and pushes a commit.

GitHub Repository: stores the site source, including the workflow file. A push to main starts a deployment.

GitHub Actions: the automated job that runs when you push to main. It authenticates with AWS, syncs updated files to S3, and tells CloudFront to clear its cache.

IAM OIDC: the OIDC identity provider registered in your AWS account. This is where AWS decides whether to trust the token GitHub Actions presents.

IAM Role: the identity the workflow assumes once AWS accepts the token. Its permissions define what the deployment is allowed to do, and nothing more.

The serving side:

S3: stores the static HTML, CSS, and any other site files. It is the only component inside the us-east-1 box.

CloudFront: the CDN that visitors reach. It handles HTTPS, caches site files at edge locations around the world, and fetches from S3 when it does not have a fresh copy.

Users: the visitors. Their browsers send HTTPS requests to CloudFront.

Reading the arrows. There are two flows in the diagram, and they read differently.

The deployment flow runs down the left and along the bottom. The developer pushes to the repository. The repository triggers GitHub Actions. GitHub Actions presents its identity token to the IAM OIDC provider. The provider's trust leads to the IAM role. The IAM role's permissions allow writing to S3. Each arrow here means "hands off to" or "is authorized by." Chapters 6, 7, and 9 explain exactly what happens at each hand-off.

The serving flow runs left to right across the bottom: S3, then CloudFront, then Users. These arrows show the direction the content travels. Files move from the origin to the edge to the visitor. The requests travel the opposite way: a visitor asks CloudFront, and CloudFront asks S3 when it needs a fresh copy. If you read every arrow as a request, the serving side looks backward. It is not wrong. It is showing content flow, and you need to know that to read it correctly.

The boundaries in this diagram.

CloudFront is public. Any internet user can reach it.

The S3 bucket is publicly readable at the object level. This exposure is intentional and scoped: the bucket policy permits read access for website serving only.

The IAM role is not internet-accessible. It is an AWS account resource that controls what GitHub Actions is permitted to do once authenticated.

The diagram does not draw an "Internet" box or an "AWS Account" box. It does not need to. The IAM OIDC provider, the IAM role, S3, and CloudFront are resources in your account. The developer, GitHub Repository, GitHub Actions, and the users are the outside world. In a larger design you would add explicit boundaries. For a system this size, the region box is enough.

Build: Read the Diagram and Find What It Leaves Out

This chapter provisions nothing and draws nothing. Its build is analytical. You will read the diagram against the system described in Chapter 1 and the requirements above, and find where the picture and the real system diverge. Every diagram diverges somewhere. Finding the gaps is the skill.

If you want to redraw the diagram yourself, is free, runs in the browser without an account, and includes the AWS icon library. It is optional. The diagram is here so you can spend your time on the build chapters instead.

Step 1: Trace the deployment path

Put your finger on the Developer icon and follow the arrows until you reach S3. Write down every component you pass through, in order. You should have six: Developer, GitHub Repository, GitHub Actions, IAM OIDC, IAM Role, S3.

Now ask what each arrow means. Is it a push, a trigger, a token, a trust relationship, a permission? Write one word next to each. You will check your answers against Chapters 6, 7, and 9.

Step 2: Trace the visitor path

Start at Users and go backward through CloudFront to S3. Write down the components you pass through. Then write down the direction a request travels and the direction the content travels. They are opposite. If you wrote the same direction for both, reread the section on arrows.

Step 3: Find what the diagram does not show

Three parts of the real system are missing from the picture. Find each one and write it down.

The first is the protocol on the CloudFront to S3 link. The diagram draws a plain arrow. In the real system this hop runs over HTTP, not HTTPS. CloudFront fetches uncached content from the S3 website endpoint, and the website endpoint does not support HTTPS. Every other hop in the system is encrypted. This one is not, and it is deliberate, not an oversight. Chapter 5 covers the trade-off and the upgrade path. Nothing on the diagram tells you this, which is why you record it yourself.

The second is the cache invalidation. The workflow does not only write to S3. After the sync, GitHub Actions sends an invalidation request to CloudFront so visitors see the new files quickly. That is a second call from the deployment side to the serving side, and the diagram draws only the S3 arrow. The IAM role carries permission for both actions.

The third is the token exchange. Between GitHub Actions and the IAM role, AWS STS (Security Token Service) validates the token and issues the temporary credentials the workflow actually uses. The diagram shows the trust relationship, not the service that issues the credentials. Chapter 7 walks through it step by step.

Step 4: Confirm what was left off on purpose

Terraform and its state backend are not in the diagram. Terraform creates everything in the picture, but it is tooling, not part of the running system. The state bucket and the lock table exist only to support Terraform. This is the "not an inventory" convention in practice. If your diagram ever needs to explain how the infrastructure was built, you draw a second diagram. You do not clutter the first.

Step 5: Save your copy

Save the diagram image somewhere you can open it while you work through the following chapters. Your knowledge base page is the natural place. You will refer back to it whenever a new resource shows up in Terraform code.

What You Just Did

You worked through the planning sequence for this project before opening any tooling. You identified what you are building, named the actual requirements, and made explicit technology choices with reasons behind them.

You then read the system's architecture diagram the way an engineer reads one: by tracing both paths, distinguishing request direction from content direction, understanding why one service sits inside the region box and the others do not, and finding the three things the picture leaves out.

That diagram is now your reference for the build chapters ahead. When a new resource shows up in Terraform code, you should already know where it sits in the picture. When something does not work as expected, the diagram is the first place to check.

Common Mistakes and How to Catch Them

Reading every arrow as a request. Arrows in architecture diagrams mean different things: triggers, trust, content flow, requests. On this diagram the serving side shows content flow, which runs opposite to the requests. Before you rely on a diagram, decide what each arrow means. If you cannot tell, that is a defect in the diagram, and worth noting.

Treating the diagram as complete. A diagram is a simplification. This one omits the HTTP hop, the cache invalidation, and the STS exchange, all of which matter when something breaks. If a system fails at a point the diagram does not show, look at the omissions first.

Placing global services inside a region box. IAM and CloudFront are global. Drawing them inside us-east-1 would misrepresent where they live. When you build your own diagrams, check each service against whether it is regional or global before you place it.

Putting every resource on the diagram. An architecture diagram is not an inventory. Terraform state storage, DynamoDB lock tables, and similar infrastructure-for-infrastructure components do not belong on a diagram of the running system. Include what helps a reader understand how the system works. Leave out what adds noise without adding clarity.

Confusing the two S3 buckets. This project has two S3 buckets: one that serves the website and one that stores Terraform state. They have completely different access controls and serve completely different purposes. Only the website bucket appears on the diagram. The state bucket is a Terraform implementation detail.

Self-Documentation

Add the following to your Book 1 — Static to Production knowledge base page:

Embed the architecture diagram image

Below the diagram, write the planning sequence in your own words: what you are building, what the requirements are, why you chose the tools you chose

Write out the deployment path and the visitor path as ordered lists of components, and note which direction requests travel on the serving side and which direction content travels

Record the three things the diagram does not show: the HTTP connection between CloudFront and S3 and why it exists, the CloudFront invalidation, and the STS token exchange

List any components in the diagram that you do not yet fully understand. Flag them as open questions. Each one has a chapter coming.

Share this chapter

Comments

0 comments

No comments yet. Start the discussion after you finish reading.