paulserban.eu

Writing Edition

Paul Serban

Writing, snippets & book notes

AWS Basics: Introduction to Amazon Web Services

What AWS really is, what it isn't, and what you should learn first (without the marketing fog)

Introduction: AWS in Plain English (and Why It Matters)

AWS (Amazon Web Services) is a giant catalog of cloud services, compute, storage, databases, networking, security, analytics, AI, and more, rented on demand. Instead of buying servers, you rent infrastructure and managed building blocks through an API and console. The value proposition is simple: speed, flexibility, and a shift from upfront capital expense to ongoing operational expense. The less glamorous reality is that AWS is also a complex ecosystem where "you can build anything" often translates to "you can accidentally misconfigure anything." AWS's own documentation frames it as "on-demand cloud computing platforms and APIs," and that's the cleanest definition available without the hype. It isn't magic; it's rented data centers plus software abstraction layers that are very good at scale.

If you're new, the hardest part isn't learning a single service, it's learning how services connect and who is responsible for what. Many people assume AWS "handles security." AWS does handle security of the cloud (facilities, hardware, foundational services), but you handle security in the cloud (identity, access, configurations, data protection). This is explicitly described by AWS as the shared responsibility model, and it's where most real-world cloud failures start: not exotic hacks, but misconfigurations, overly broad permissions, exposed storage, missing encryption, or logs not enabled. AWS will let you shoot yourself in the foot; it will also give you excellent tools to avoid doing so, if you use them.

Context: The AWS Mental Model - Accounts, Regions, and Availability Zones

Before services, you need the map. AWS is organized into Regions (geographic areas like us-east-1) and Availability Zones, or AZs (separate data centers within a region designed for fault isolation). This structure matters because nearly every design decision is tied to it: latency, redundancy, compliance, and cost. "Multi-AZ" is not a buzzword; it's a practical way to survive a single data center failure. "Multi-region," by contrast, is a different beast, carrying higher complexity and cost and usually being unnecessary until there's a clear business reason for it. AWS documents this structure plainly in its Global Infrastructure documentation, and internalizing it early explains why some services are regional, some are global, and some require explicit replication.

Now the part people don't like hearing: AWS doesn't prevent you from designing fragile systems in one region, one AZ, or even one instance. It won't stop you from running a production database on a single virtual machine because it's cheaper today. Cloud computing makes it possible to build resilient systems, but it does not make resilience automatic. When AWS talks about "high availability," it's describing what the platform enables, not what your architecture guarantees by default. This distinction is one of the most common sources of frustration for teams new to the platform, since the marketing language around cloud resilience can imply guarantees that only materialize if you explicitly design for them.

The beginner win is learning to separate the idea of where things run (regions and AZs) from what things do (compute, storage, databases). Once you make that separation, you stop being overwhelmed by the sheer number of service names and start thinking in reliable patterns instead: this workload needs multi-AZ redundancy, this one doesn't; this data needs to stay in a specific region for compliance reasons, this one doesn't. AWS's Well-Architected Framework, specifically its Reliability pillar, formalizes this thinking and is worth reading even at a beginner level, since it frames reliability as a set of deliberate design choices rather than a property you inherit simply by being "on the cloud."

Core Services You Actually Need First

If you want the shortest path to "I can build and run something," focus on three categories. Compute includes EC2 (virtual machines), ECS and EKS (containers), and Lambda (serverless functions). Storage includes S3 (object storage) and EBS (block storage attached to EC2 instances). Databases include RDS and Aurora (managed relational databases) and DynamoDB (managed NoSQL). AWS offers dozens of additional services, but most beginner projects can be expressed with a mix of these seven. S3, for example, is a foundational service: durable object storage with an HTTP interface, lifecycle policies, and integration nearly everywhere else in AWS. It's also one of the easiest places to leak data if you don't understand access policies, block public access settings, and IAM permissions.

Here's the honest trade-off: AWS gives you choices that look similar but carry radically different operational burdens. EC2 is flexible but pushes patching, scaling decisions, and maintenance onto you, unless you wrap it with additional services. Lambda reduces server management but introduces its own constraints, such as execution timeouts and event-driven architectural patterns. RDS reduces database operations but still requires choosing instance sizes, storage, backup schedules, maintenance windows, and network placement. DynamoDB removes even more operational overhead, but it demands that you model your data's access patterns carefully and understand partitioning and capacity modes upfront. Beginners often bounce between services trying to find "the best" one, when the more productive question is what you're willing to manage yourself. The platform doesn't remove trade-offs; it relocates them to a different layer of the stack.

Networking Fundamentals: VPC, Subnets, and Security Groups

AWS networking is where many new users stall. The main construct is the VPC, or Virtual Private Cloud: your isolated network environment within AWS. Inside a VPC, you create subnets (public or private), route tables, and gateways, an Internet Gateway for public internet access, and a NAT Gateway for outbound-only access from private subnets. You then layer on security groups (stateful virtual firewalls at the instance or resource level) and network ACLs (stateless controls applied at the subnet level). This all sounds abstract until you debug your first "my app can't reach the database" incident. Most of these failures aren't mysteries; they're mismatched routes, missing inbound rules, wrong ports, or resources sitting in private subnets without a NAT path out.

A practical way to think about AWS networking is that routing decides where packets can go, and security rules decide whether they're allowed to. Engineers new to AWS mix these up constantly. You can open a security group on port 443 and still have zero connectivity if your route table doesn't send traffic to the right gateway. Conversely, you can have a perfectly correct route and still be blocked entirely by security group rules. The cloud doesn't make networking inherently easier; it makes networking programmable, which becomes genuinely powerful once you're comfortable with the underlying model.

Start small: one VPC, two subnets (public and private), one EC2 instance in the public subnet as a test endpoint, and one RDS instance in the private subnet. Learn this "minimum viable wiring" pattern thoroughly, because it's the foundation nearly every more complex AWS architecture builds on top of. Once this specific setup makes sense end to end, from an inbound request hitting the public EC2 instance to that instance querying the private RDS database, the rest of AWS networking (load balancers, multiple AZs, peering, transit gateways) is mostly variations and extensions of this same core pattern rather than fundamentally new concepts.

Identity and Security Fundamentals: IAM and the Shared Responsibility Reality Check

If you only learn one security concept first, make it IAM, Identity and Access Management. IAM controls who can do what to which resource, and it's the difference between "safe by default" and "oops, someone deleted production." AWS provides IAM users, groups, roles, and policies as the building blocks of this system. Modern best practice is to avoid long-lived access keys, prefer roles and temporary credentials instead, and enforce least privilege throughout. AWS's own guidance pushes toward centralized identity management, often through IAM Identity Center, and multi-factor authentication wherever possible, because credential theft remains one of the most common real-world failure modes in cloud environments. IAM policy syntax is powerful but unforgiving: a single misplaced wildcard can grant far more access than intended.

The shared responsibility model is the second pillar here. AWS is responsible for the security of the underlying cloud infrastructure, but you control IAM policies, network exposure, encryption settings, data classification, logging, and monitoring. This isn't a scare tactic; it's a contractual division of labor. If your S3 bucket is publicly accessible, that is typically not "AWS leaked your data," it's a configuration that you or your tooling applied. AWS does provide guardrails like S3 Block Public Access, AWS Config, CloudTrail, and Security Hub, but these are tools, not guarantees; they only help if someone actually configures and monitors them. A mature AWS setup usually includes enforced MFA, strict role-based access, centralized logging, and automated checks that detect configuration drift over time. Beginners can start with three concrete steps: enable CloudTrail, use MFA everywhere, and avoid creating broad administrative policies unless genuinely necessary.

Pricing Realities: The Part Marketing Won't Feel in Your Budget Review

AWS pricing isn't "expensive" or "cheap" in the abstract; it's granular. You pay for usage: compute time, storage measured in GB-months, requests, data transfer, managed service throughput, and sometimes for features you didn't realize were billable, such as NAT Gateways or certain logging volumes. The trap is that your final bill is the sum of many small, individually reasonable-looking meters. AWS provides several tools to manage this, including the Pricing Calculator, Cost Explorer, budgets, and alerts, but the responsibility to forecast and control spend remains yours. Many teams overspend not because they're careless, but because the pricing model itself rewards continuous attention: rightsizing instances, turning off idle resources, choosing the correct storage class, and designing to reduce cross-AZ or internet egress traffic where it genuinely matters.

The "free tier" deserves a specific mention here, since it's often misunderstood. It is not a safety net; it's closer to a learning coupon. Some services have permanently free portions, others are free only for 12 months, and many costs, especially data transfer and managed networking components, can surprise engineers who assume "cloud is generally cheap for small projects." NAT Gateway charges are a common example: they can become non-trivial if you route significant traffic through them, since you pay for both hourly usage and data processing separately. Logging can also get expensive if verbose logs are enabled without ever setting retention limits.

The honest recommendation here is boring, but boring advice is usually the advice that actually works: set budgets and alerts on day one, tag every resource consistently (environment, owner, service), and delete what you don't use. AWS cost control isn't about one clever trick; it's continuous hygiene, closer to a recurring engineering practice than a one-time setup task.

A Practical Example: Uploading to S3 Safely

To make this concrete, here's a minimal Python example that uploads a file to S3 using the official AWS SDK, boto3. This assumes you're using credentials provided via environment variables or an IAM role, which is the preferred approach, rather than hardcoding access keys directly. AWS SDKs are well documented and widely used, and S3's API is one of the most stable entry points into AWS as a whole. The bigger lesson here isn't the code itself; it's the workflow: use least-privilege credentials, target a specific bucket, and handle errors explicitly rather than letting failures pass silently.

import boto3
from botocore.exceptions import ClientError

def upload_file(bucket: str, key: str, filename: str) -> None:
    s3 = boto3.client("s3")
    try:
        s3.upload_file(
            Filename=filename,
            Bucket=bucket,
            Key=key,
            ExtraArgs={
                # Server-side encryption with S3-managed keys (SSE-S3).
                # For stricter controls, many organizations use SSE-KMS instead.
                "ServerSideEncryption": "AES256"
            },
        )
        print(f"Uploaded {filename} to s3://{bucket}/{key}")
    except ClientError as e:
        raise RuntimeError(f"S3 upload failed: {e}") from e

if __name__ == "__main__":
    upload_file(bucket="my-private-bucket", key="uploads/report.pdf", filename="report.pdf")

The honest caveat here: this code can be "correct" while your overall setup is still unsafe. If the IAM principal running this script has s3:* permissions on *, you've effectively granted unlimited object access across your entire account, regardless of how carefully this specific function is written. The right approach is to scope permissions to a single bucket, and often a specific key prefix within it, and to deny public access at the bucket level unless it's explicitly and deliberately required for a distribution use case, often served instead through CloudFront. AWS's policy language and S3 bucket policies are powerful enough to enforce these guardrails precisely, but only if you choose to write and apply them rather than relying on tribal knowledge about "how we usually configure buckets."

Trade-offs and Common Pitfalls

The core trade-off across nearly all of AWS is flexibility versus guardrails: the platform is deliberately permissive, because restricting what's possible would undermine the "build anything" value proposition that draws people to it in the first place. But this same permissiveness means AWS won't stop you from making costly or dangerous mistakes unless you've explicitly configured protections against them. A single-instance production database, a public S3 bucket, an overly broad IAM policy, none of these will trigger an error from AWS; they're all valid configurations that AWS will run without complaint, and the responsibility for recognizing them as risks falls entirely on the engineer or team building the system.

A second, related pitfall is treating infrastructure-as-code as a starting point rather than something adopted after manual understanding. Tools like Terraform or the AWS Cloud Development Kit are genuinely valuable for making infrastructure reviewable, repeatable, and version-controlled, but codifying a misunderstood architecture just produces a repeatable mistake instead of a repeatable success. It's generally more effective to build something manually first, understand exactly what each piece does and why, and only then translate that understanding into infrastructure-as-code, rather than copying a Terraform module from the internet without fully grasping what it provisions.

A third pitfall is treating cost and security as someone else's job, typically finance or a security team, rather than as first-class engineering concerns owned by the people actually building the system. Retrofitting logging, monitoring, or cost controls onto an existing system is meaningfully harder than designing them in from the start, since gaps in visibility tend to compound silently over time rather than announcing themselves immediately.

Best Practices: Five Key Actions to Get Value From AWS Quickly

The fastest way to get real value from AWS isn't to "learn AWS" as an abstract goal; it's to learn a small set of repeatable practices that prevent the most common mistakes. Pick a basic architecture pattern, such as a static site with an API and a database, or a batch job with storage, and implement it using a deliberately limited service set rather than reaching for every available option. Enable core security and logging early, since retrofitting visibility later is genuinely painful compared to designing it in from the beginning. Treat cost controls as part of engineering practice, not as a finance department's afterthought. Adopt infrastructure-as-code only after you've built something manually at least once, so you actually understand what you're automating rather than automating an opaque black box. Finally, design with failure in mind: use multiple Availability Zones when a workload genuinely warrants that resilience, and back up data as though you actually intend to restore it someday, not as a checkbox exercise.

In concrete, actionable terms, this looks like: create separate accounts, or at minimum separate environments, for development and production wherever feasible. Turn on CloudTrail and set log retention intentionally rather than leaving it at whatever the default happens to be. Use IAM roles paired with MFA, avoid long-lived access keys, and keep permissions as narrow as the task genuinely requires. Set AWS Budgets and alerts, and tag resources consistently with fields like environment, owner, and service. Start with a single region and multi-AZ redundancy where it actually matters, rather than defaulting to multi-region complexity without a clear business justification for it. None of this guarantees perfection, but it substantially reduces the chance of waking up to a surprising bill, a publicly exposed bucket, or an outage that basic architectural hygiene would have prevented.

Analogies and Mental Models

A useful mental model for AWS is a well-stocked hardware store combined with a construction crew for hire, rather than a pre-built house. The store has virtually every component you could need, lumber, wiring, plumbing fixtures, power tools, and it will happily sell you exactly what you ask for, whether or not what you're building with those components is structurally sound. Nobody at the checkout counter is going to stop you from buying materials for a house with no foundation; that's precisely the role AWS plays with services like EC2, S3, or IAM policies. The tools for building something genuinely resilient, load-bearing walls, proper foundations, electrical code compliance, all exist and are well documented (AWS's Well-Architected Framework plays this role), but using them correctly is a decision you have to make deliberately, not a property of the materials themselves.

This analogy also clarifies the shared responsibility model cleanly: the hardware store is responsible for the quality and availability of the materials themselves, wiring that doesn't have manufacturing defects, lumber that meets a stated grade, but it is not responsible for whether you wire your house correctly or whether your foundation can support the second story you're planning. Where the analogy breaks down somewhat is around elasticity and cost: unlike a hardware store transaction, which is a discrete, one-time purchase, most AWS billing is continuous and usage-based, closer to a utility bill that keeps running as long as a resource exists, which is part of why unused or forgotten resources are a distinctly cloud-specific cost risk rather than a physical hardware one.

The 80/20 of Learning AWS

Of everything covered here, a small number of ideas do most of the practical work for engineers getting started with AWS. First, internalizing regions and Availability Zones clarifies why certain services behave the way they do and why "multi-AZ" is a meaningful reliability decision, not a marketing term. Second, understanding the shared responsibility model, specifically that AWS secures the cloud while you secure what you put in it, explains the overwhelming majority of real-world security incidents, which tend to be misconfigurations rather than platform failures. Third, learning IAM deeply, specifically the principle of least privilege and the preference for roles over long-lived keys, prevents the most damaging class of mistakes a beginner can make.

Beyond these three ideas, a working knowledge of one compute service, one storage service, and one database service, along with basic VPC networking (public versus private subnets, security groups versus routing), covers the large majority of what beginner-to-intermediate projects actually require. Deeper topics, specific pricing optimization strategies, multi-region architectures, or the internals of specific managed services' consistency guarantees, matter significantly for specialists and for systems operating at real scale, but they're refinements built on top of this core foundation rather than prerequisites for getting started productively.

Key Takeaways

Conclusion: AWS Is a Toolbox - Your Outcomes Depend on Your Discipline

AWS is the most widely adopted cloud platform for a reason: it offers a mature set of services, genuinely global infrastructure, and a deep surrounding ecosystem. But the beginner-friendly story is only half true. AWS does not remove complexity; it gives you the ability to manage complexity incrementally, one deliberate decision at a time. Approach it like a buffet, sampling a little of everything without a clear plan, and you'll get overwhelmed and build fragile systems. Approach it like a toolbox, picking the right tool for a specific job, learning the safety rules first, and practicing a small set of core patterns, and you'll progress quickly while avoiding the worst and most common pitfalls.

The most honest advice available here is this: don't chase service count, chase clarity. Learn regions and Availability Zones, learn IAM thoroughly, learn VPC basics, and pick one compute path, one storage path, and one database path to start. Build something small, measure what it actually costs, and add guardrails deliberately rather than reactively. AWS rewards teams that treat cloud infrastructure as engineering work, not as a shopping trip through a service catalog. Once that foundation is genuinely in place, the rest of the AWS catalog stops looking like undifferentiated noise and starts looking like a set of real options, ones you can evaluate calmly, with trade-offs you actually understand rather than trade-offs you discover the hard way in production.

References

Resources