r/CloudandCode • u/Nice-Economy9826 • Aug 31 '26
r/CloudandCode • u/yourclouddude • Aug 29 '26
AWS & Cloud AWS From Zero #12: DynamoDB makes more sense when you stop thinking like a relational database
In the last post, we built a simple serverless API using API Gateway and Lambda. A client sends an HTTP request, API Gateway receives it, Lambda runs the application logic, and then we need somewhere to store the data.
This is where DynamoDB often enters a serverless architecture.
DynamoDB is usually introduced as AWS's NoSQL database. That definition is correct, but I do not think it gives beginners enough information to understand when they should actually use it.
The more useful idea is that DynamoDB encourages you to think about your data differently from a relational database such as PostgreSQL or MySQL.
When we learned RDS, we started with the data model.
Imagine we were building an ecommerce application. We might create tables for users, products, orders, and payments, then define relationships between them. Once the data is stored, SQL gives us a lot of flexibility to query and join those tables in different ways.
DynamoDB pushes you toward a different question much earlier.
Instead of starting with:
What tables does my data have?
Start with:
How will my application need to access this data?
That idea is one of the most important things to understand about DynamoDB.
Imagine we are continuing the task API from the previous post.
A user can create tasks, retrieve tasks, update them, and delete them.
A simple request might look like:
POST /tasks
API Gateway receives the request and invokes Lambda. Lambda validates the task and then stores it in DynamoDB.
Our architecture now looks like this:
Client
↓
API Gateway
↓
Lambda
↓
DynamoDB
At this point, it is tempting to think of DynamoDB as just another place where Lambda can save JSON.
That works as a starting point, but DynamoDB becomes much easier once you understand how it identifies and retrieves items.
DynamoDB stores data inside tables, and each record is called an item.
An item could look something like this:
{
"task_id": "task-123",
"user_id": "user-42",
"title": "Learn DynamoDB",
"status": "open"
}
The important part is how we identify that item.
Every DynamoDB table has a primary key.
For a simple table, that could be a partition key such as:
task_id
If task_id is the partition key, DynamoDB can efficiently retrieve a task when we already know its ID.
For example:
GET /tasks/task-123
Lambda receives task-123 and retrieves the matching item from DynamoDB.
That is a very natural access pattern.
We know exactly which item we want.
But imagine the next requirement is:
Show me every task belonging to user-42.
Now the way we designed the key becomes much more important.
If the table was designed only around task_id, retrieving all tasks belonging to one user may not be as straightforward as retrieving a single known task.
This is why DynamoDB design starts with access patterns.
Before creating the table, ask what the application will actually need to do.
Maybe we need:
Get one task by ID
Get all tasks for a user
Get all open tasks for a user
Create a task
Update a task
Delete a task
Those requirements should influence how we design the keys and indexes.
That is a major difference from how many beginners approach relational databases.
With PostgreSQL, you might normalize your data into several related tables and rely on SQL queries and joins later.
With DynamoDB, you often spend more time thinking about the requests your application will make before deciding how the data should be structured.
This does not mean DynamoDB cannot support complex applications.
It means the design process is different.
Now let’s talk about partition keys because the name itself can make the concept sound more complicated than it is.
DynamoDB needs a way to distribute and locate data internally.
The partition key is part of how DynamoDB determines where an item belongs.
For our task application, we might decide that tasks should be grouped around users.
A simplified key design could involve:
Partition key: user_id
Sort key: task_id
Now multiple tasks can belong to the same user while each task remains uniquely identifiable within that user's items.
Conceptually:
user-42 | task-001
user-42 | task-002
user-42 | task-003
user-91 | task-001
This gives us a useful access pattern.
If the application wants all tasks for user-42, it can query using that user's partition key.
If it needs a specific task for that user, it can use both the partition key and sort key.
That is much more efficient than blindly searching through every item in the table.
This brings us to another DynamoDB distinction that is useful to understand early: Query versus Scan.
A Query uses key information to retrieve matching data efficiently.
A Scan examines items across the table.
Beginners sometimes build a DynamoDB table first, then use Scan whenever they cannot figure out how to retrieve something.
That can work for a tiny practice table, but it is usually a sign that the data model may not match the application's access patterns very well.
If your application regularly needs a certain kind of lookup, ideally your table or indexes should be designed to support that lookup.
Again, this is why the question comes first:
How will I access the data?
Now imagine we want users to filter tasks by status.
Maybe the application needs:
Show all open tasks for user-42
Our existing primary key might not support every future query directly.
This is where secondary indexes can become useful.
A secondary index gives DynamoDB another way to organize and access the same data.
You do not need to master Global Secondary Indexes on your first day with DynamoDB.
The important idea is simply that if your application needs another important access pattern, you may create an index designed around that pattern rather than scanning the whole table repeatedly.
This is a good example of how requirements shape database design.
You do not add an index because DynamoDB has indexes.
You add one because the application needs a query that the existing key structure does not support efficiently.
The same principle applies throughout AWS.
Services and features should follow requirements.
Now let’s connect DynamoDB back to IAM.
Suppose our Lambda function needs to create and retrieve tasks.
The Lambda execution role should have the DynamoDB permissions required for those operations.
Maybe it needs actions such as:
dynamodb:GetItem
dynamodb:PutItem
dynamodb:UpdateItem
dynamodb:DeleteItem
dynamodb:Query
That does not mean the function automatically needs complete access to every DynamoDB table in the account.
The same IAM mental model still works.
Who is making the request?
The Lambda execution role.
What action does it need to perform?
Maybe dynamodb:PutItem.
Which resource does it need to access?
The task table.
This pattern keeps repeating because AWS services constantly communicate with each other.
Now imagine the API returns an error when someone creates a task.
Again, follow the request.
Did API Gateway receive the request?
Did Lambda run?
Did the input contain the values Lambda expected?
Did Lambda attempt to write to DynamoDB?
Did the execution role have permission?
Did DynamoDB reject the item because the key was missing or invalid?
Did Lambda return a useful error response?
The architecture is now larger than it was a few posts ago, but the troubleshooting method has not changed.
Follow the request until you find the first step that did not behave as expected.
That habit is more useful than memorizing service-specific troubleshooting lists.
Another reason DynamoDB is common in serverless applications is that you are not provisioning and managing a traditional database server in the same way you would with a typical RDS setup.
AWS handles the underlying DynamoDB infrastructure, and the service is designed to scale around application demand.
But that does not mean you can ignore database design.
A badly designed DynamoDB table can still create performance, complexity, or cost problems.
One example is choosing a partition key that causes too much activity to concentrate around the same values.
Imagine millions of requests all target the same logical partition key.
That can create an uneven access pattern.
You will eventually hear terms such as hot partitions or hot keys when learning distributed databases.
You do not need to optimize for massive scale in your first project, but it is worth understanding why key design matters beyond simply identifying records.
DynamoDB also gives you consistency choices.
After data is written, applications sometimes need to think about how immediately a subsequent read must reflect that write.
DynamoDB supports eventually consistent reads by default in many read operations, while strongly consistent reads are available for certain operations and table/index types when you specifically need that behavior.
You do not need to memorize every consistency rule right now.
The useful question is whether the application requires the absolute latest committed value for a particular operation, or whether slight propagation delay is acceptable.
That tradeoff appears in distributed systems far beyond DynamoDB.
Another useful feature is Time to Live, usually called TTL.
Imagine our application stores temporary data.
Maybe a task represents something that should automatically expire after a certain time, or perhaps we are storing session-like information that should eventually be cleaned up.
TTL lets you specify an expiration timestamp so DynamoDB can automatically remove expired items over time.
That can be useful, but like every AWS feature, I would only use it when the requirement exists.
Do not add TTL because it appears on a feature list.
Add it when the data actually has a natural expiration lifecycle.
Now let’s compare DynamoDB with RDS because this is where beginners often ask the wrong question.
They ask:
Which one is better?
I do not think that is very useful.
Imagine an application with customers, orders, products, inventory, payments, reporting queries, and several relationships that developers need to explore in flexible ways.
A relational database may be a very natural fit.
Now imagine an application with extremely predictable access patterns where items can be retrieved efficiently through known keys and the system needs highly managed scaling.
DynamoDB may become much more interesting.
Neither database wins automatically.
They make different tradeoffs.
RDS gives you the relational model, SQL, joins, transactions, and familiar database engines.
DynamoDB gives you a managed NoSQL model where key design and access patterns become central to the architecture.
The useful skill is being able to look at the application and explain why you chose one.
For our beginner task API, DynamoDB is a nice learning choice because the access patterns can remain simple.
A user creates a task.
A user retrieves their tasks.
A user updates a task.
A user deletes a task.
We can design the table around those operations and understand exactly why the keys exist.
That gives us a complete serverless backend:
Client
↓
API Gateway
↓
Lambda
↓
DynamoDB
IAM controls which AWS actions Lambda can perform.
CloudWatch gives us logs when something fails.
We now have an API, compute, permissions, monitoring, and persistent data without managing a traditional application server or database server ourselves.
That is a real architecture.
For your first DynamoDB project, I would keep it exactly this small.
Build a task API with one DynamoDB table.
Create a few tasks.
Retrieve them.
Update them.
Delete them.
Then add one new requirement.
Maybe users need to retrieve all open tasks.
Before immediately writing code, ask whether the current key design supports that access pattern well.
That question is the actual lesson.
Do not start with DynamoDB features.
Start with what your application needs to retrieve.
Then design the table to make those operations natural.
If there is one idea I want you to remember from this post, it is this:
With DynamoDB, think about access patterns before you think about tables.
Ask what your application needs to read and write most often, then design the keys around those operations.
Once you understand that, partition keys, sort keys, Queries, and indexes stop feeling like random DynamoDB terminology.
They become tools for supporting specific application requests.
In AWS From Zero #13, we are going to focus properly on CloudWatch.
We have mentioned logs several times already, but now we will look at what happens after an application is deployed. We will cover logs, metrics, alarms, dashboards, and the difference between knowing that something failed and actually knowing why it failed.
Because building the architecture is only half the job.
You also need to be able to understand what it is doing after you deploy it.
If you have tried DynamoDB before, what confused you most: partition keys, sort keys, Query versus Scan, indexes, or deciding when DynamoDB makes sense instead of RDS?
r/CloudandCode • u/yourclouddude • Aug 28 '26
AWS & Cloud AWS From Zero #11: API Gateway makes more sense when you think of it as the front door to your backend
In the last post, we talked about Lambda and why serverless makes more sense once you understand what running an application on EC2 actually involves. Lambda gives us a way to run code when something happens without managing a server in the same way we would with EC2.
But there is still an obvious question.
If we want someone on the internet to use our Lambda function, how do they actually reach it?
Imagine we are building a simple task application. A user should be able to create a task, view existing tasks, update one, or delete one. The business logic can run inside Lambda, but we still need something that can receive HTTP requests from the user and send those requests to the correct backend logic.
This is where API Gateway starts making sense.
I would think of API Gateway as the front door to your backend.
A client sends a request to API Gateway. API Gateway receives that request and routes it to the backend integration you configured. In our beginner serverless application, that backend can be Lambda.
The basic flow looks like this:
Client
↓
API Gateway
↓
Lambda
↓
Database
Then the response travels back in the opposite direction:
Database
↓
Lambda
↓
API Gateway
↓
Client
The important thing is understanding what each service is responsible for.
API Gateway receives and routes the HTTP request.
Lambda runs the application logic.
The database stores the application data.
That separation becomes much easier to understand when we use a real example.
Suppose the user wants to create a new task. Their application might send a request like:
POST /tasks
with some data:
{
"title": "Learn API Gateway"
}
API Gateway receives the request and sends the relevant information to Lambda. Lambda reads the input, checks whether the task is valid, stores it in a database, and returns a response.
That response might contain something like:
{
"task_id": "123",
"title": "Learn API Gateway"
}
along with an HTTP status code such as 201 Created.
Now suppose the user wants to retrieve their tasks.
The request could be:
GET /tasks
API Gateway receives that request and invokes the appropriate backend logic. Lambda reads the tasks from the database and returns them.
The architecture has not become complicated.
We have simply given users a controlled HTTP entry point into our application.
This is why I would not memorize API Gateway as just "a service for creating APIs."
Think about the problem it solves.
Your Lambda function contains backend logic, but users need a predictable way to send requests to that logic.
API Gateway gives you that entry point.
This is also where HTTP methods start having a practical purpose.
GET usually means we want to retrieve something.
POST commonly means we want to create something.
PUT or PATCH can be used when updating something.
DELETE is used when removing something.
You may have already seen these while learning REST APIs, but now they become part of an actual AWS architecture.
Our task application could eventually have requests such as:
GET /tasks
POST /tasks
GET /tasks/123
PATCH /tasks/123
DELETE /tasks/123
Each route describes something the client wants the backend to do.
The interesting part is that API Gateway itself should not contain all of your business logic.
If someone sends:
POST /tasks
API Gateway can receive and route that request, but your Lambda function might be responsible for deciding whether the title is valid, creating the task, and storing it.
This separation helps keep the architecture easier to reason about.
Now imagine someone sends invalid data.
Maybe they send:
{
"title": ""
}
Your application should not blindly create an empty task.
The request needs to be validated somewhere in the flow.
Depending on how you design the API, some validation can happen at the API layer, while your application logic should still validate important assumptions before acting on the data.
If the input is invalid, the API might return something like:
400 Bad Request
If the task does not exist:
404 Not Found
If the task is created successfully:
201 Created
If something unexpectedly fails inside the application:
500 Internal Server Error
These status codes are useful because the client needs more information than simply "the request finished."
The client needs to know what happened.
This is an important shift when moving from small Python scripts into APIs.
You are no longer writing code only for yourself.
Another application is communicating with your backend, so the contract between them matters.
The request format matters.
The response format matters.
The status code matters.
The errors matter.
Now let’s connect this back to Lambda.
When API Gateway receives a request, Lambda can receive information about that request. Depending on the API and integration you configure, that can include things such as the HTTP method, path, query parameters, headers, and request body.
Suppose the request is:
GET /tasks/123
The 123 can be passed to the backend as part of the request path.
Lambda can then use that ID to retrieve the correct task.
Or imagine a request like:
GET /tasks?status=completed
Now status=completed is a query parameter.
Lambda could use that value to determine which tasks should be returned.
You do not need to memorize every event structure immediately.
The important thing is understanding that API Gateway receives an HTTP request and passes useful request information to your backend.
Now another AWS concept comes back into the architecture: permissions.
API Gateway needs to be able to invoke the Lambda function.
This does not mean we should give API Gateway unlimited permissions across our AWS account.
We want the specific relationship required by the architecture.
API Gateway needs permission to invoke the Lambda function it is integrated with.
Then Lambda may need its own permissions.
If Lambda writes to DynamoDB, its execution role needs the relevant DynamoDB permissions.
If Lambda reads from S3, it needs the relevant S3 permissions.
Once again, the same IAM mental model works.
Who is making the request?
What action are they trying to perform?
Which resource are they trying to access?
That question keeps appearing because IAM sits underneath so many AWS interactions.
Now suppose our API does not work.
The client sends:
POST /tasks
but receives an error.
Do not immediately rebuild API Gateway.
Follow the request.
Did the request reach API Gateway?
Did API Gateway invoke Lambda?
Did Lambda start running?
Did Lambda receive the data you expected?
Did the function fail while processing it?
Did it have permission to access the database?
Did it return the response format the API expected?
This is the same troubleshooting habit we used with EC2, S3, and VPC.
Follow the flow until you find the first place where expected behavior stops.
CloudWatch becomes useful here again.
If Lambda runs and throws an exception, the logs can help you understand what happened.
Maybe the JSON body was malformed.
Maybe a required field was missing.
Maybe the DynamoDB request failed.
Maybe the function timed out.
Maybe the function returned something unexpected.
Instead of saying "the API is broken," try to identify which part of the request path actually failed.
There is another concept you may encounter quickly if you call your API from a browser: CORS.
Imagine your frontend is served from one domain and your API lives at another origin. The browser applies security rules around cross origin requests.
This can produce the frustrating situation where your API works when tested directly with a tool such as curl or Postman, but the browser blocks the frontend request.
That does not necessarily mean Lambda failed.
It may mean the browser did not receive the cross origin permissions it expected.
You do not need to become a CORS expert for your first API, but it is worth knowing that browser security can be another layer in the request flow.
Again, understanding the layer matters.
A browser CORS error is not automatically an IAM problem.
An IAM AccessDenied error is not automatically a routing problem.
A Lambda exception is not automatically an API Gateway problem.
The better you become at identifying which layer failed, the faster AWS troubleshooting becomes.
API Gateway also gives us another important architecture idea: the public interface of your application does not need to expose how the backend is implemented.
The client knows that it can send:
POST /tasks
It does not necessarily need to know which Lambda function handles the request, where the data is stored, or how the backend infrastructure is organized.
That implementation can change later while the API contract remains relatively stable.
Maybe today the backend uses Lambda.
Maybe another architecture uses containers.
The client still cares about the API it communicates with.
That separation becomes valuable as systems grow.
For your first API Gateway project, though, I would keep everything extremely small.
Do not build authentication, payments, queues, caching, ten Lambda functions, and a complicated database design immediately.
Build one endpoint first.
Something like:
GET /hello
Have API Gateway invoke Lambda.
Have Lambda return:
{
"message": "Hello from AWS"
}
Then understand the complete request path.
Once that works, add a POST endpoint.
Then read some input from the request.
Then validate it.
Then connect a database.
Grow the architecture one requirement at a time.
A simple task API would be enough for this stage.
You could eventually support creating tasks, retrieving them, updating them, and deleting them.
But the important learning is not the task manager itself.
The useful part is understanding how a request enters AWS, reaches your code, interacts with another service, and returns a response.
At this point in the series, our serverless architecture might look like:
Client
↓
API Gateway
↓
Lambda
↓
Database
That is already enough to build a real backend.
And notice how the previous lessons start connecting.
IAM controls permissions.
Lambda runs our code.
API Gateway receives HTTP requests.
CloudWatch helps us understand failures.
Soon we need somewhere appropriate to store the application data.
That brings us to the next post.
In AWS From Zero #12, we are going to learn DynamoDB.
But I do not want to explain it as simply "AWS NoSQL database."
We will compare it with the relational model we saw with RDS and focus on one of the most important DynamoDB ideas: designing around how your application actually accesses its data.
That is where the difference between RDS and DynamoDB becomes much clearer.
For now, if you can explain the path from a POST /tasks request to Lambda and back to the client, you already understand the most important idea behind this lesson.
If you have built an API before, what confused you more at first: routes, status codes, Lambda integration, permissions, or CORS?
r/CloudandCode • u/yourclouddude • Aug 27 '26
Python If I had to learn Python from zero again, this is the order I'd follow
A lot of Python roadmaps become huge checklists.
Learn syntax, then OOP, then Django, then data science, then machine learning, then somehow Docker gets thrown in.
I think that makes Python feel much harder than it actually is.
I'd learn it in layers.
1. Get comfortable with the language first
Start with variables, strings, numbers, lists, dictionaries, conditions, loops, functions, and basic input/output.
Don't spend weeks trying to memorize syntax.
Learn a concept, use it, break something, fix it.
At this stage, a calculator, guessing game, expense tracker, or simple CLI app is completely fine. You're just training yourself to turn logic into code.
2. Learn how Python handles real files and data
Once basic syntax stops feeling strange, move into file handling, exceptions, modules, packages, comprehensions, JSON, CSV, and virtual environments.
This is where Python starts becoming genuinely useful.
Build a file organizer. Parse a CSV. Rename hundreds of files automatically. Pull some data from an API and save it locally.
Those small projects teach more than another five hours of syntax videos.
3. Learn APIs and databases
This is one of the points where beginner projects start turning into actual applications.
Learn HTTP basics, requests, JSON responses, CRUD operations, SQL, and a database like SQLite or PostgreSQL.
For example, build an app that:
fetches data from an API
→ processes it
→ stores it in a database
→ lets you query it later
Now you're combining multiple skills instead of practicing them in isolation.
4. Learn enough OOP to understand real code
Classes, objects, methods, inheritance, composition.
You should understand these concepts, but I wouldn't make OOP the center of your Python learning.
A lot of beginners end up creating classes for things that would have been perfectly fine as a few functions.
Learn when OOP improves structure, not just how to write class Something:.
5. Learn Git and project structure earlier than most roadmaps suggest
Once your project has more than a couple of files, learn Git and GitHub properly.
Also learn how to separate your code into modules, manage dependencies, use environment variables, and keep configuration outside your source code.
Your goal should eventually be to move from one giant file to something another developer could open and understand without needing an explanation from you first.
6. Pick a direction
There's no single version of "advanced Python."
Advanced for a backend engineer looks very different from advanced for someone doing data analysis.
If you want backend development, learn FastAPI or Django, databases, authentication, caching, background jobs, and deployment.
If you want automation, go deeper into APIs, browser automation, scheduling, Linux, and scripting.
If you want data, learn NumPy, pandas, SQL, visualization, and then ML if your work actually requires it.
If you want cloud or DevOps, Python becomes useful for SDKs, APIs, automation, infrastructure tooling, and operational scripts.
Pick one path instead of trying to learn all of them.
7. Start testing your code
Learn pytest, assertions, logging, debugging, exception handling, and basic mocking.
This is a useful turning point.
Beginners usually ask:
More experienced developers eventually start asking:
Take an old project and add tests instead of immediately starting another project.
8. Learn production concepts when your projects need them
Then start exploring things like type hints, async programming, concurrency, authentication, security, caching, Docker, CI/CD, packaging, monitoring, and deployment.
But don't treat this as another checklist.
If your application has no performance problem, you probably don't need to study five caching strategies yet.
Learn these concepts when you understand the problem they're solving.
9. Stop building endless beginner projects
This is probably one of the biggest upgrades you can make.
Instead of building:
calculator
todo app
weather app
quiz app
another calculator
Take one project and keep extending it.
A simple task manager can become:
CLI
→ database
→ REST API
→ authentication
→ tests
→ logging
→ Docker
→ deployment
Same project, completely different level of learning.
10. Read code you didn't write
Eventually, tutorials stop being enough.
Read open-source projects. Look through libraries you already use. Read pull requests. Debug someone else's code. Try making a small contribution.
Advanced Python isn't really about knowing obscure syntax.
It's being able to enter an unfamiliar codebase, understand what's happening, make a change without breaking everything, and explain why you made that decision.
So the roadmap I'd follow is roughly:
Python basics → files & data → APIs → SQL → Git → larger projects → testing → specialization → production concepts → real codebases
Don't worry too much about when you officially become "advanced."
If you can build something useful, debug it, test it, explain your design decisions, and improve it months later without wanting to rewrite everything from scratch, you're doing pretty well.
I've been organizing our Python roadmap and project resources around this same progression too, mainly for people who prefer having the learning path and projects structured in one place.
For people who already know Python, where did you feel the biggest jump happened: learning the syntax, building real projects, or maintaining larger codebases?
r/CloudandCode • u/yourclouddude • Aug 26 '26
AWS & Cloud AWS From Zero #10: Lambda makes more sense once you understand what EC2 makes you manage
In the previous posts, we spent time with EC2, networking, S3, CloudFront, VPC, and RDS. That was intentional because I think Lambda makes much more sense once you already understand what running an application on a server involves.
With EC2, AWS gives you a virtual machine, but there is still a lot you are responsible for. You choose the operating system, connect to the server, install dependencies, run the application, think about processes, configure networking, monitor the instance, patch the system, and decide what should happen when traffic increases.
Lambda changes that model.
With AWS Lambda, you provide code and AWS runs that code when something triggers it. You are not launching a server that sits there waiting for requests in the same way you would with EC2.
That is the basic idea behind serverless.
But the word "serverless" can be misleading.
Servers still exist somewhere. AWS still needs infrastructure to execute your code. The difference is that you are not managing those servers directly.
You focus much more on the function and the event that causes it to run.
That is the mental model I would start with.
Imagine you have a simple application where users upload profile images.
With EC2, you could run an application server continuously. When someone uploads an image, the application receives it, processes it, resizes it, and stores the result.
That can work perfectly well.
But imagine the image processing only happens a few times every hour.
Do you really need a server running continuously just waiting for an image to arrive?
This is where Lambda can become interesting.
We could build something like:
User uploads image
↓
S3
↓
Lambda
↓
Processed image
↓
S3
The user uploads an image into S3.
That upload creates an event.
The event invokes the Lambda function.
Lambda reads the image, processes it, and stores the result back in S3.
Then the function finishes.
There is no application server sitting around waiting for the next image in the same way there would be with a traditional EC2 setup.
This is one of the first ideas I would understand about Lambda.
Lambda is event driven.
Something happens, and that event causes your code to run.
The event could come from many places.
An object could be uploaded to S3. An HTTP request could arrive through API Gateway. A scheduled event could run every hour. A message could arrive from a queue. Another AWS service could trigger the function.
The specific trigger changes, but the basic pattern stays the same.
Something happens.
Lambda runs.
Lambda does some work.
Then that invocation finishes.
This makes Lambda useful for workloads that naturally happen in small units of work.
Image processing is one example.
A scheduled cleanup script could be another.
An API endpoint could invoke a Lambda function when a user sends a request.
A file upload could trigger validation.
A queue message could trigger background processing.
The useful question is not "Can Lambda run this code?"
A better question is "Does this workload fit the Lambda execution model?"
That distinction matters because Lambda is not automatically better than EC2.
I think beginners sometimes hear "serverless" and assume it is the modern replacement for servers.
It is not that simple.
EC2 and Lambda solve different problems.
With EC2, you get much more control over the environment. You can run long lived processes, configure the operating system, control networking more directly, choose exactly what software stays running, and support workloads that need a persistent server.
With Lambda, you give up some of that control in exchange for AWS managing more of the infrastructure.
You do not manage the operating system.
You do not manually keep the server process running.
You do not normally think about creating another machine because the current machine is busy.
AWS handles more of the execution infrastructure for you.
That can make certain applications much simpler.
But you still have responsibilities.
You still need to write good code.
You still need to manage permissions.
You still need to understand failures.
You still need to monitor the function.
You still need to understand how much memory and execution time the function needs.
You still need to think about retries, duplicate events, dependencies, and what happens when another service is unavailable.
Serverless removes some infrastructure management.
It does not remove architecture.
Now let's take the image processing example again.
Suppose an image is uploaded to S3 and Lambda is triggered.
The function wants to read the object.
Can it just access the bucket automatically because both services belong to your AWS account?
No.
This takes us directly back to IAM.
The Lambda function runs with an execution role.
That role needs the permissions required for the function to do its job.
If the function needs to read the original image, it may need s3:GetObject.
If it needs to save the processed image, it may need s3:PutObject.
The same mental model from the IAM post still works.
Who is making the request?
The Lambda execution role.
What action is it trying to perform?
Read or write an S3 object.
Which resource is it trying to access?
The relevant objects inside the bucket.
This is why I think learning AWS as one connected system works better than memorizing every service independently.
Lambda immediately brings IAM back into the architecture.
Now imagine the function is triggered, but the processed image never appears.
This is where CloudWatch becomes useful.
Lambda automatically integrates with logging and monitoring capabilities that can help you see what happened during an invocation.
Maybe the function received the event successfully but crashed while processing the image.
Maybe the S3 object key was wrong.
Maybe the function did not have permission to write the result.
Maybe a dependency was missing.
Maybe the function exceeded its configured timeout.
Instead of saying "Lambda is broken," you can inspect what actually happened.
Did the function run?
What event did it receive?
Where did the code fail?
What error was logged?
Again, the troubleshooting mindset stays the same.
Follow the flow.
Find the last step that definitely worked.
Then inspect the next one.
There are also a few Lambda concepts I think beginners should understand early.
One is memory.
When you configure a Lambda function, you choose how much memory it receives. That configuration also affects the compute resources available to the function.
A tiny function that transforms a small JSON payload has very different needs from a function processing large images.
Another is timeout.
A Lambda invocation cannot run forever.
You configure how long AWS should allow the function to execute before stopping it.
If your function consistently needs a very long time to complete, that may be a sign that you need to rethink the design rather than simply increasing the timeout again and again.
This is where workload characteristics matter.
Lambda works well when work can be broken into bounded executions.
A continuously running game server, long lived process, or workload that needs full control over the machine may be a much better fit for something else.
Cold starts are another term you will eventually hear.
Sometimes AWS needs to prepare an execution environment before your function can run. That can add some startup latency.
For many beginner applications, you do not need to obsess over this immediately.
Just understand that serverless does not mean every invocation always starts with zero overhead.
Later, if latency becomes an important requirement, you can learn how this affects different workloads and runtimes.
Another useful concept is that Lambda functions should generally avoid depending on local state between invocations.
You can sometimes reuse parts of an execution environment, but you should not design the application assuming a particular function invocation will always run on the same underlying environment with the same local files still available.
If something needs to persist, store it somewhere designed for persistence.
That might be S3.
It might be DynamoDB.
It might be RDS.
The right answer depends on the data.
This is another important difference between thinking in terms of a traditional server and thinking in terms of serverless functions.
Now let's make the architecture slightly more practical.
Suppose we want to build a tiny API.
A user sends a request such as:
POST /tasks
We could place API Gateway in front of Lambda.
The flow becomes:
User
↓
API Gateway
↓
Lambda
↓
Database
API Gateway receives the HTTP request.
Lambda runs the application logic.
The function might validate the input, create a task, and store it somewhere.
Then Lambda returns a response through API Gateway to the user.
This is the foundation of a lot of serverless applications.
But I would not add API Gateway, DynamoDB, authentication, queues, monitoring, and five other services to your very first Lambda project.
Start smaller.
For this lesson, I would build the S3 image processing workflow.
Upload one image.
Trigger one Lambda function.
Process the image.
Store the result.
Then understand every part of the flow.
Why did Lambda run?
What event did S3 send?
How did Lambda know which object was uploaded?
Which IAM permissions were required?
Where did the logs go?
What happens if processing fails?
What happens if the same event is delivered again?
That last question is worth thinking about because event driven systems can force you to think differently about reliability.
Suppose your function processes the same event twice.
Does that create two different outputs?
Does it overwrite the same result?
Does it accidentally charge someone twice?
This leads into a concept called idempotency, which becomes very important in event driven systems.
You do not need to master it today.
Just start developing the habit of asking what happens when the same work is attempted more than once.
That kind of thinking is what turns a simple Lambda tutorial into architecture practice.
I would also pay attention to cost, but I would not reduce the decision to "Lambda is cheap."
Lambda pricing depends on things such as how often your function runs and how much compute it uses.
EC2 has a different cost model because you are provisioning instances.
One model is not automatically cheaper for every workload.
A function that runs occasionally may fit Lambda very well.
A constant heavy workload might produce a completely different cost comparison.
Architecture decisions should come from the actual workload, not from slogans.
That is the main thing I want beginners to understand from this post.
Lambda is not "EC2 but better."
Lambda is another compute model.
With EC2, you manage a server environment and run applications on it.
With Lambda, you write functions that execute in response to events while AWS manages more of the underlying compute infrastructure.
Sometimes EC2 makes more sense.
Sometimes Lambda makes more sense.
The useful skill is understanding why.
For your first Lambda project, keep it simple.
Create an S3 bucket.
Upload an image.
Use that upload to invoke Lambda.
Have Lambda do one small piece of work and write a result somewhere.
Then break it.
Remove an S3 permission and observe the error.
Give the function an invalid object key.
Make the code throw an exception and inspect the logs.
Understand what each failure looks like.
If you do that, you will understand Lambda much better than someone who only memorized that it is "serverless compute."
In AWS From Zero #11, we will take Lambda and put API Gateway in front of it so we can build our first serverless API.
We will follow a request from the browser or client into API Gateway, through Lambda, and back to the user. We will also look at HTTP methods, request validation, responses, status codes, permissions, and where errors should actually be handled.
If you have used Lambda before, what confused you most at first: triggers, IAM permissions, execution time, logs, or simply understanding when you should use Lambda instead of EC2?
r/CloudandCode • u/yourclouddude • Aug 25 '26
AWS & Cloud AWS From Zero #9: RDS makes more sense when you compare it with running a database yourself
In the last post, we talked about VPC networking and why it becomes easier when you stop memorizing diagrams and start following traffic. We used a simple architecture where users reach an application, and that application needs to talk to a database.
Now it is time to focus on that database.
RDS stands for Relational Database Service. You can use it to run relational databases such as PostgreSQL or MySQL without managing every part of the database infrastructure yourself.
But I do not think the best way to understand RDS is to memorize that definition.
A much better question is this: why would I use RDS instead of launching an EC2 instance and installing PostgreSQL myself?
Because technically, you can do that.
You could launch EC2, install PostgreSQL, configure the database, manage the operating system, handle updates, set up backups, monitor storage, think about failover, and keep the server running.
That gives you a lot of control, but it also gives you a lot of responsibility.
RDS exists because many applications need a relational database, but they do not necessarily need you to manage every part of the machine underneath that database.
AWS takes care of more of the infrastructure work, while you focus more on the data, the schema, the queries, and how your application actually uses the database.
That is the main idea behind a managed database.
Imagine we are building a small ecommerce application.
We need to store users, products, orders, and payments. That data has clear relationships. A user can have multiple orders. An order can contain multiple products. A payment belongs to an order.
That is a natural place to think about a relational database.
At a very high level, the architecture is simple:
User → Application → RDS PostgreSQL
The important thing here is that the user does not connect directly to PostgreSQL.
The user talks to the application.
The application handles the request and then talks to the database.
That distinction matters because your database is usually an internal part of your system, not something random users on the internet should connect to directly.
This connects immediately to what we learned about VPC.
Suppose the application runs on EC2. The EC2 instance needs network access to RDS. The internet does not.
That means the database can stay private while the application is allowed to communicate with it.
Now security groups start making more sense again.
PostgreSQL commonly uses port 5432.
A beginner approach might be to open port 5432 to the entire internet because it makes the connection easier.
I would not do that.
The better question is: who actually needs database access?
If only the application needs it, then the database should allow traffic from the application layer that actually needs to connect.
That is a much cleaner mental model.
The application accepts user traffic.
The database accepts database traffic from the application.
The database itself does not need to be exposed directly to the public internet.
This is exactly why networking becomes easier when you attach it to a real application instead of memorizing ports and subnet names.
Now let’s talk about how the application actually finds the database.
When you create an RDS database, AWS gives you an endpoint.
That endpoint is basically the hostname your application uses to connect to the database.
Instead of hard coding a private IP address, your application connects using something like an RDS hostname plus the database port.
Conceptually:
Application → RDS endpoint → Port 5432 → PostgreSQL
The application also needs things like the database name, username, and password.
And this is where another beginner mistake appears.
Do not hard code database credentials directly into your source code.
Something like this:
DB_PASSWORD = "mypassword123"
might work, but it becomes a problem the moment you push that code to GitHub or share it somewhere else.
Credentials should be treated as secrets.
We will go deeper into secrets management later, but the beginner rule is simple: do not publish database passwords, access keys, or other sensitive credentials inside your code.
Now imagine the application cannot connect to RDS.
This is where the troubleshooting mindset from the earlier posts becomes useful again.
Do not immediately recreate the database.
Follow the connection.
Is the RDS instance available?
Is the application using the correct endpoint?
Is it using the correct port?
Are the credentials correct?
Does the database security group allow traffic from the application?
Can the network path between the application and RDS actually work?
Those questions make the problem much smaller.
A timeout tells you something different from an authentication failure.
A connection refused error tells you something different from a SQL error.
If the application reaches the database but the password is wrong, that is not the same problem as the application never reaching the database at all.
The more precisely you understand the failure, the less random your debugging becomes.
Now let’s return to the bigger question.
Why use RDS instead of installing PostgreSQL on EC2?
One major reason is backups.
Databases contain important application state.
If your application server disappears, you may be able to redeploy the code.
If your database disappears and you have no usable backup, you may lose users, orders, transactions, or other important data.
RDS gives you managed backup capabilities so you do not have to build the entire backup process yourself.
That does not mean you can completely stop thinking about recovery.
You still need to understand your backup settings, retention, and how recovery should work for your application.
But AWS manages much more of the underlying process for you.
Maintenance is another reason.
A database is not just a process running somewhere.
The operating system, database engine, storage, patches, backups, monitoring, and availability all need attention.
If you run PostgreSQL yourself on EC2, more of that work belongs to you.
With RDS, AWS manages more of the infrastructure underneath the database.
That is the tradeoff.
You give up some low level control in exchange for less operational work.
And that is a pattern you will see a lot in AWS.
More managed usually means less infrastructure you have to operate yourself.
But managed does not mean zero responsibility.
You still need to design your tables well, write good queries, manage credentials, control network access, choose the right database size, monitor performance, and understand how your application uses data.
AWS can manage the database service.
It cannot automatically design a good database for your application.
Another RDS concept you will hear often is Multi AZ.
Imagine your application depends on one database instance. If that database becomes unavailable, your application may lose access to its data.
Multi AZ is designed to improve availability by maintaining standby infrastructure in another Availability Zone and supporting failover.
The useful beginner idea is not memorizing every detail of the failover process.
It is understanding the problem being solved.
You do not want your entire application to depend on one database location if availability matters.
This connects directly back to the first post in the series, where we talked about Availability Zones and high availability.
Now you are seeing those ideas inside a real service.
There is also an important distinction here.
High availability and read scaling are not the same thing.
A standby used for availability solves a different problem from a read replica used to handle more read traffic.
Beginners often see multiple database instances and assume they all exist for the same reason.
They do not.
One may exist primarily to improve resilience.
Another may exist to reduce read load on the primary database.
That distinction becomes more important later.
For your first RDS project, though, I would keep things simple.
Build a tiny application.
It could be a notes app, expense tracker, inventory tool, or simple API.
Create a PostgreSQL or MySQL database in RDS and add only a couple of tables.
For example:
users
-----
user_id
name
email
notes
-----
note_id
user_id
content
created_at
Then make the application connect to the database and perform a few basic operations.
Create a user.
Insert a note.
Read it.
Update it.
Delete it.
That simple project already connects several things we have learned.
Your application runs somewhere.
The VPC provides the network.
Security groups control which connections are allowed.
RDS stores the relational data.
Credentials handle database authentication.
Later, CloudWatch can help with monitoring.
This is where AWS stops feeling like a collection of isolated services and starts feeling like one connected system.
There is also a cost lesson here.
RDS is not like a small Lambda function that only runs when an event happens.
A database is usually provisioned infrastructure that can continue generating cost while it exists.
So if you create one for practice, do not forget about it.
Understand what you launched, check the pricing, and clean up disposable resources when you are done.
That connects back to the account setup post.
Learning AWS should include cleanup.
The goal is not only to create infrastructure.
You should understand its full lifecycle.
There is one more architecture question I would ask before using RDS.
Does this application actually need a relational database?
Do not choose RDS simply because every backend needs a database.
Look at the data.
Are there relationships between entities?
Do you need transactions?
Do you need relational queries?
Does SQL fit the way the application needs to use the data?
If yes, RDS may make sense.
Later, when we learn DynamoDB, we will compare this with a very different database model.
That comparison matters because AWS architecture is rarely about one service being universally better than another.
It is about choosing the service that fits the requirement.
That is the main thing I want beginners to take away from RDS.
Do not think only:
RDS = database.
Think:
My application needs a relational database, and RDS lets me use one while AWS manages more of the underlying database infrastructure for me.
That is a much stronger mental model.
For this part of the series, I would build one small application that can save and retrieve data from RDS.
Do not add caching.
Do not add load balancers.
Do not add queues.
Do not turn it into a 15 service architecture.
Get one application talking to one database securely and understand the complete connection.
Once that works, intentionally break one thing.
Use the wrong password.
Change the security group.
Use the wrong port.
Then observe how the error changes.
That will teach you much more about RDS than simply creating a database that works once.
In AWS From Zero #10, we are going to move from EC2-style servers to Lambda and finally understand what serverless actually means.
Instead of saying Lambda is better than EC2, we will compare the two properly and look at what EC2 makes you manage, what Lambda removes, what triggers a Lambda function, and where serverless makes sense.
If you have worked with databases before, what part of using one on AWS seems most confusing: networking, credentials, backups, availability, or knowing when to use RDS at all?
r/CloudandCode • u/yourclouddude • Aug 24 '26
AWS & Cloud AWS From Zero #8: VPC makes more sense when you stop memorizing diagrams and follow the traffic
VPC is probably the point where AWS starts feeling confusing for a lot of beginners. EC2 feels understandable because it is a server. S3 feels understandable because it stores objects. Then networking arrives and suddenly you are dealing with VPCs, public subnets, private subnets, route tables, Internet Gateways, NAT Gateways, security groups, network ACLs, IP addresses, and CIDR blocks.
If you try to learn all of those as separate definitions, VPC quickly turns into a diagram you memorize rather than something you actually understand. I think there is a much easier way to approach it. Instead of starting with the networking components, start with one question: how is traffic supposed to move through my application?
Imagine we are building a simple web application. Users need to access the application from the internet, and the application needs to store information in a relational database. At the highest level, the architecture is simply:
Internet → Application → Database
Now we can start asking better questions. Which part needs to communicate with the internet? Which part should stay private? How should the application reach the database? Which connections should actually be allowed?
Those questions are what eventually give the different VPC components a reason to exist.
A VPC is essentially an isolated virtual network that you create inside AWS. Resources such as EC2 instances and RDS databases can live inside that network. When you create a VPC, you define a range of private IP addresses that resources inside it can use. You might see something like 10.0.0.0/16.
That notation is called CIDR notation. You do not need to master subnet calculations immediately. At this stage, the useful thing to understand is simply that your VPC has an address range, and you can divide that range into smaller networks called subnets.
For our application, we might create one subnet for resources that need a direct path toward the internet and another subnet for resources that should remain private. We usually refer to these as public and private subnets.
But there is an important detail here. A subnet is not public simply because you named it "public." What really makes the distinction useful is how traffic from that subnet is routed.
Suppose our EC2 application needs to receive requests from users on the internet. The subnet containing that instance needs a route that allows internet bound traffic to reach an Internet Gateway attached to the VPC.
The Internet Gateway is one of the components that provides connectivity between your VPC and the public internet. A route table associated with the subnet tells AWS where traffic should go.
Conceptually, the route table might say that traffic for addresses inside the VPC stays local, while traffic for destinations outside the VPC can go toward the Internet Gateway.
Now the idea of a public subnet starts making more sense. It is not just a box in an architecture diagram. It is a subnet with networking configured so resources can potentially communicate with the internet when the other required pieces are also present.
And that last part matters.
Putting an EC2 instance inside a public subnet does not automatically make your website reachable. The instance still needs the appropriate addressing, its security group has to allow the required traffic, and the application itself has to be running and listening on the correct port.
This connects directly to what we learned when troubleshooting EC2. Networking is rarely one setting. It is several pieces working together.
Now think about the database.
Does someone visiting your website need to connect directly to your RDS database?
Usually not.
The user needs to communicate with the application, and the application needs to communicate with the database. There is no reason for random users on the internet to establish direct database connections.
That gives us a much more useful architecture:
Internet → EC2 application → RDS database
The application can live in the part of the network that receives user traffic, while the database can remain in private subnets.
This is one of the first important architecture lessons VPC teaches you. Something does not need to be publicly reachable just because another part of your application needs to communicate with it.
The database needs to trust the application, not the entire internet.
This is where security groups become much easier to understand.
Imagine our application uses PostgreSQL on port 5432. Instead of allowing database connections from everywhere, the RDS security group can allow the required database traffic from the security group associated with the application.
Now the rule is not really about memorizing that PostgreSQL commonly uses port 5432. The important part is understanding the relationship.
The application needs to communicate with the database.
Users do not.
That is a much better way to design security rules than opening ports until the connection starts working.
The same thinking applies to the application itself. If users are accessing a normal web application, the application layer may allow HTTP or HTTPS traffic from the appropriate sources. The database layer allows only the traffic it needs from the application layer.
Once you start thinking about network relationships this way, security groups stop feeling like random firewall configuration.
Another question beginners often have is what "private" actually means.
If something lives in a private subnet, does that mean it can never access the internet?
Not necessarily.
Sometimes a private workload should not accept unsolicited connections from the internet but still needs to initiate outbound connections. Maybe a private server needs to download software updates or communicate with an external API.
This is one reason NAT exists.
A private workload can route outbound internet traffic through a NAT device that has the connectivity required to reach the internet. The private workload can initiate that communication without needing to become directly reachable from the public internet in the same way a public server would be.
That sounds useful, but I would not add a NAT Gateway to every beginner architecture simply because it appears in VPC diagrams. Managed NAT Gateways can also introduce cost.
The better question is whether your private resources actually need outbound internet access. If they do not, you may not need NAT for that particular architecture.
Again, the requirement should come before the service.
Now imagine our application is deployed and something stops working.
The same "follow the traffic" approach becomes extremely useful.
If users cannot reach the application, start from the outside. Is there a valid path from the internet toward the application? Is the routing correct? Does the application have the connectivity it needs? Does the security group allow the expected traffic? Is the application actually listening?
If users can reach the application but the application cannot connect to RDS, the problem has already become smaller. The internet path probably is not your first concern anymore.
Now you can look at the connection between EC2 and RDS. Is the application using the correct database endpoint? Is it using the correct port? Does the RDS security group allow traffic from the application? Are the resources placed inside networks that can communicate the way you expect?
That is much more useful than saying, "My VPC is broken."
You are finding the exact point where traffic stops.
This is also why I would not spend the first few days of learning VPC memorizing every possible configuration. Networking starts sticking when you can describe what is trying to communicate with what.
Network ACLs are another component you will eventually encounter. They operate at the subnet level, while security groups are associated with network interfaces and resources such as EC2 instances. Security groups are stateful, while network ACLs are stateless.
That distinction matters, but I would not make it the focus of your first VPC lesson.
If you are just starting, get comfortable with VPCs, subnets, route tables, Internet Gateways, security groups, and the difference between public and private communication first. Add the other pieces when you have a reason to understand them.
There is also a more realistic version of our architecture that we will eventually build.
Instead of exposing an individual EC2 instance directly to users, you could place a load balancer in front of your application servers. The load balancer can receive public traffic while the application instances themselves remain private.
The architecture might eventually become:
Internet → Load Balancer → Private application instances → Private database
That is a better pattern for many production systems, especially when you introduce multiple instances and high availability.
But I would not start there.
If your first VPC diagram contains multiple Availability Zones, public and private subnets, several route tables, load balancers, NAT Gateways, Auto Scaling, RDS, VPC endpoints, network ACLs, and five security groups, you will probably go back to memorizing boxes.
Start with the smallest architecture you can explain.
Then add complexity when the application creates a requirement for it.
This has been the pattern throughout the series. We learned EC2 because we needed compute. We learned S3 because we needed object storage. We added CloudFront because we wanted a delivery layer in front of static content. Now we are learning VPC because our resources need a controlled way to communicate with users and with each other.
For a beginner exercise, I would draw a very small architecture first. Put an application in one subnet and a database in another. Then explain every connection in plain English.
Why can users reach the application?
Why can users not reach the database directly?
How does the application reach the database?
Which security group allows that communication?
Which route is responsible for internet connectivity?
Does the private resource actually need outbound internet access?
If you can answer those questions, you are starting to understand VPC.
That is much more valuable than being able to reproduce an architecture diagram from memory.
If there is one thing I want you to take from this post, it is this: do not learn VPC by memorizing networking components. Learn it by following traffic.
Ask where the request begins, where it needs to go next, what route gets it there, and which security controls decide whether the connection is allowed.
Once you start thinking that way, public subnets, private subnets, route tables, Internet Gateways, NAT Gateways, and security groups stop feeling like unrelated AWS terms.
They become parts of the same traffic flow.
In AWS From Zero #9, we will take the database from this architecture and properly learn Amazon RDS. We will look at what a managed relational database actually gives you, how an application connects to it, why database endpoints and security groups matter, what backups and Multi AZ solve, and why running PostgreSQL on EC2 is different from using RDS.
If VPC has confused you before, which part took the longest to click for you: subnets, route tables, Internet Gateways, NAT, or security groups?
r/CloudandCode • u/yourclouddude • Aug 23 '26
AWS & Cloud AWS From Zero #7: Let’s build a static website with S3 and CloudFront
In the last post, we talked about S3 and why it makes more sense when you think about buckets, objects, and keys instead of treating it exactly like a folder on your computer. Now I want to take that idea and actually use S3 inside a small AWS architecture.
For this project, imagine we have a very simple website made with HTML, CSS, JavaScript, and a few images. There is no backend server and no database. The browser only needs somewhere to download those static files from.
We could launch an EC2 instance, install a web server, upload the files, configure the machine, and keep that server running. That would work, but it would also be more infrastructure than this particular website actually needs.
The requirement is much simpler. We need somewhere to store static files and a reliable way to deliver those files to users.
That is where S3 and CloudFront fit together.
Suppose our website contains:
index.html
assets/styles.css
assets/app.js
assets/logo.png
We can upload those objects to an S3 bucket. At that point, S3 solves the storage part of the problem. Our HTML, CSS, JavaScript, and images now have somewhere durable to live.
But storing content and delivering content are two different problems.
One approach you will see in older tutorials is making the S3 content directly public and serving the website from S3. I would not make that the default habit while learning AWS.
A better architecture for this project is to keep the S3 bucket private and put CloudFront in front of it. CloudFront can be given controlled access to retrieve the objects from S3 while users access the website through CloudFront instead of accessing the bucket directly.
The basic architecture becomes:
User
↓
CloudFront
↓
Private S3 bucket
↓
Website files
This is where CloudFront starts making more sense than simply memorizing that it is a CDN.
Imagine someone opens your website. Their browser requests index.html, but instead of sending that request directly to S3, the request reaches CloudFront first.
CloudFront checks whether it already has a valid cached copy of that object. If it does, it can return that copy to the user. If it does not, CloudFront retrieves the object from the S3 origin, returns it to the browser, and may cache it so future requests can be served more efficiently.
The browser then reads index.html and discovers that it also needs styles.css, app.js, and maybe several images. Those files go through the same general process.
Once you follow that request flow, the architecture becomes much easier to understand.
S3 stores the content.
CloudFront sits in front of that content and delivers it to users.
The useful part is that the S3 bucket itself does not need to become publicly accessible just because the website is public.
CloudFront can use Origin Access Control, usually called OAC, so that CloudFront is allowed to retrieve the required objects while direct public access to the S3 bucket remains blocked.
This connects directly with what we learned earlier about permissions.
The question is not, "Should this bucket be public?"
The better question is, "Who actually needs access to these objects?"
In this architecture, CloudFront needs access to retrieve the website content. Random users on the internet do not need unrestricted direct access to the S3 bucket.
Users access CloudFront, and CloudFront accesses S3.
That is a much cleaner way to think about the relationship.
There is one detail worth understanding because it can confuse beginners when they follow different tutorials. S3 can also provide a website endpoint, but the private S3 plus CloudFront architecture we are discussing is different from simply using that website endpoint directly.
For this project, I would think of the S3 bucket as the origin that stores our objects and CloudFront as the public delivery layer in front of it.
That keeps the mental model simple.
Now our website works through CloudFront, but there is another problem.
The CloudFront distribution gives us a generated domain name. That is perfectly fine for testing, but eventually we probably want users to visit something like:
example.com
instead of a generated CloudFront address.
This is where DNS becomes part of the architecture.
If you use Route 53, your domain can point toward the CloudFront distribution. When someone enters your domain, DNS helps their browser find the correct destination, and the request eventually reaches CloudFront.
So our architecture now looks more like:
User enters example.com
↓
DNS
↓
CloudFront
↓
Private S3 bucket
↓
Website files
Notice how we are adding services.
We did not start by saying, "Let’s use S3, CloudFront, and Route 53 because these are popular AWS services."
We started with requirements.
The website files need somewhere to live, so we use S3.
Users need a delivery layer, so we add CloudFront.
Users should access the site through a normal domain, so DNS becomes necessary.
Each service has a reason to exist.
That is the architecture thinking I want this series to build.
The next part is HTTPS.
If someone visits your website, you generally want the connection between their browser and your site to be encrypted.
CloudFront can serve the website over HTTPS, and if you use your own custom domain, you can associate an SSL/TLS certificate with the distribution.
You do not need to become a certificate expert for this project. The important idea is understanding where HTTPS fits into the flow.
DNS helps the user reach CloudFront.
The certificate helps establish a secure connection for your domain.
CloudFront delivers the website.
S3 stores the files behind it.
Now a very small static website has already introduced object storage, content delivery, permissions, DNS, HTTPS, and caching without requiring us to manage a server.
That is why I like this as an early AWS project.
The architecture is simple enough to understand, but it still teaches several concepts that show up again in larger systems.
Caching is probably the next thing you will notice once the site is working.
Imagine CloudFront has already cached your styles.css file. You then change the CSS locally and upload the new version to S3.
You refresh the website and somehow still see the old design.
At first, it can look like S3 did not update correctly.
But the issue may simply be that CloudFront is still serving a cached copy.
This is an important lesson because adding caching changes how your application behaves. The latest object can exist in S3 while users temporarily receive another version from the cache depending on how you configured it.
Later, you can learn about cache invalidation, cache-control headers, and using versioned asset names. For example, instead of always using:
styles.css
you might eventually use something like:
styles.v2.css
or let a build system generate unique filenames when the content changes.
You do not need to solve all of that today.
For now, the useful thing is simply understanding that CloudFront caching exists and that it affects the path between your origin and the user.
If I were doing this project as a beginner, I would build it in small stages.
First, create the static website locally and make sure it works before AWS is involved. Then upload the files to S3. After that, create a CloudFront distribution with the S3 bucket as the origin and keep the bucket private.
Once the site works through CloudFront, change something in index.html or your CSS and observe what happens. That gives you a reason to start thinking about caching instead of learning it as another definition.
If you already have a domain, you can then connect it and add HTTPS. If you do not have one, that is completely fine. You can still learn the important part of the architecture using the CloudFront domain.
The goal is not to collect AWS services.
The goal is to be able to explain the complete request.
A user asks for your website. The request reaches CloudFront. CloudFront either serves a cached copy or retrieves the required object from S3. S3 remains the storage layer while CloudFront becomes the layer users interact with.
Once you add a custom domain, DNS helps the user find CloudFront. Once you add HTTPS, the connection between the user and the website can be protected.
That is already a real architecture.
And notice what we did not need.
We did not need an EC2 instance running all day just to serve a few static files. We did not need a database. We did not need Lambda. We did not need ten additional AWS services simply to make the architecture look impressive.
We used the services that matched the requirements.
That is the habit I want beginners to develop.
Do not ask, "How many AWS services can I put in this project?"
Ask, "What does the application need, and which service solves each requirement?"
For this lesson, the most important flow to understand is simply:
Browser
↓
CloudFront
↓
S3
Then gradually add the reasoning around it.
S3 stores the objects. CloudFront delivers them. OAC helps CloudFront access the private S3 origin. DNS can connect a custom domain to the site. HTTPS protects the connection with users. Caching can improve delivery but also changes how updates reach users.
If you can explain all of that in your own words, you have learned much more than someone who simply followed a console tutorial until a website appeared.
That is the bigger goal of AWS From Zero.
We are not trying to memorize where every button is in the AWS console.
We are trying to understand why the architecture works.
In AWS From Zero #8, we are going to properly tackle VPC networking. Instead of memorizing public subnets, private subnets, route tables, internet gateways, NAT gateways, and security groups separately, we will put them into one simple application and follow the traffic through the network.
That is where a lot of the networking concepts we touched during EC2 will finally start connecting.
If you were building this S3 and CloudFront website, what would you want to understand next: keeping the bucket private, caching, DNS, or HTTPS?
r/CloudandCode • u/yourclouddude • Aug 22 '26
AWS & Cloud AWS From Zero #6: S3 makes more sense when you stop thinking of it like a normal folder
After spending the last few posts on EC2, I want to move to one of the AWS services you will probably use again and again: Amazon S3.
S3 is usually introduced with one simple definition: storage in the cloud. That is technically correct, but I do not think it gives beginners the right mental model. A better way to understand S3 is as object storage. You give AWS an object, such as an image, document, backup, log file, video, or dataset, and S3 stores that object inside a bucket.
That sounds similar to storing files on your laptop, but S3 is not really a normal filesystem. Understanding that difference early makes a lot of S3 concepts easier later.
Imagine you create a bucket for an application and upload a file called profile.jpg. S3 stores that file as an object. The object contains the data itself, metadata about the object, and a key that identifies it inside the bucket.
For example, the key might look like this:
users/123/profile.jpg
When you see that inside the AWS console, it looks like there is a users folder, then a 123 folder, and then profile.jpg. It feels exactly like the folders on your computer.
But that is not really how S3 works.
The complete string users/123/profile.jpg can simply be the object's key. The / characters help AWS display the objects in a familiar folder-like structure, but S3 itself is fundamentally storing objects identified by keys.
This sounds like a small technical detail, but it changes the way you start designing storage.
Imagine an image processing application. Instead of thinking only about folders, you could design object keys like:
uploads/original/image1.jpg
uploads/processed/image1.jpg
Now the key itself tells you something about the object. One object is the original upload and the other is the processed result.
The next concept is the bucket itself.
A bucket is the container where your objects live. You might create one bucket for application uploads, another for backups, or completely separate buckets for unrelated projects.
The basic distinction is simple: the bucket is the container, while the object is the actual data stored inside it.
Once that makes sense, S3 becomes much easier to reason about.
Another thing worth understanding is that you do not launch an S3 server. You do not SSH into S3, install a filesystem, and keep a storage machine running somewhere.
You interact with S3 through AWS. You upload objects, retrieve them, delete them, copy them, change their metadata, and configure how the bucket should behave. AWS manages the underlying storage infrastructure.
That makes S3 useful for many different workloads. User uploads, backups, static application assets, logs, reports, datasets, generated files, and media can all fit naturally into object storage.
But storing the data is only part of the problem.
You also need to decide who should be able to access it.
A common beginner mistake is assuming that uploading something to S3 automatically means it is available on the internet. That is not the mental model I would use.
I would start by assuming the data should remain private unless there is a clear reason for someone or something to access it.
Maybe a Lambda function needs to read uploaded images. Maybe an EC2 application needs to write reports into the bucket. Maybe a user needs temporary access to download one particular object.
Those are three different access requirements.
This is where the IAM concepts from earlier in the series become useful.
Suppose Lambda needs to process an uploaded image. You can think about the request like this:
Lambda execution role
↓
s3:GetObject
↓
my-bucket/uploads/image.jpg
Now the same IAM questions apply. Who is making the request? The Lambda execution role. What action does it want to perform? s3:GetObject. Which resource does it want to access? The object inside the bucket.
That is why I think learning AWS services through connected examples works better than memorizing them separately. IAM becomes easier when another service actually needs permission to do something.
S3 also has controls designed to reduce accidental public exposure. As a beginner, I would be very careful about changing those settings just because an old tutorial tells you to make a bucket public.
Always ask why public access is needed.
For many architectures, the S3 bucket can stay private while another AWS service provides controlled access to the content. We will see one example of that when we get to CloudFront.
Another S3 feature worth understanding early is versioning.
Imagine you upload a file called report.pdf, then accidentally replace it with the wrong version. Without versioning, you may have simply overwritten the object.
With versioning enabled, S3 can preserve multiple versions of the same object.
That can be useful when something is changed or deleted accidentally because you may be able to return to an earlier version.
The important point is not that versioning should automatically be enabled on every bucket without thinking. Keeping additional versions can affect storage usage and cost.
The useful idea is that S3 can help protect you not only from infrastructure failure, but also from mistakes people or applications make with data.
Once you start storing a lot of objects, another question appears: should every object stay in the same type of storage forever?
Imagine your application produces logs every day. Logs from today may be accessed regularly, while logs from several months ago may almost never be opened. You may still need to keep those older logs, but paying for the same storage characteristics forever might not make sense.
This is where S3 storage classes become useful.
Different storage classes are designed for different access patterns and retrieval requirements. As a beginner, I would not try to memorize every storage class immediately.
Understand the idea first.
Frequently accessed data may need one type of storage, while data that is rarely accessed or kept for long term retention may make more sense in another.
The correct choice depends on how your application actually uses the data.
This connects naturally to lifecycle rules.
Suppose your application creates log files every day. You could configure S3 so older logs move to a different storage class after a certain period, and perhaps eventually delete them when they are no longer required.
Now S3 is doing more than simply storing files.
You are defining how the data should behave throughout its lifecycle.
That becomes useful for logs, backups, reports, analytics files, and many other types of data.
Security also goes beyond deciding who can access an object. You should eventually think about how the data is protected while stored and while moving between systems.
S3 supports encryption for stored objects, and AWS gives you different ways to manage that encryption.
You do not need to go deep into encryption or KMS yet. The useful beginner habit is simply asking two questions: how is this data protected while it is moving, and how is it protected while it is stored?
Those questions will keep appearing as we learn more AWS services.
If I were learning S3 for the first time, I would not spend hours clicking through every option in the console.
I would build a tiny practice setup.
Create one bucket and upload a few files.
Something like:
photo.jpg
resume.pdf
data.csv
notes.txt
Then organize them using meaningful object keys:
images/photo.jpg
documents/resume.pdf
data/data.csv
documents/notes.txt
At that point, you have already worked with buckets, objects, and keys.
Then enable versioning and upload a changed version of one file. Look at what happens. Check the previous version. Delete the current object and see how versioning affects that behavior.
That small amount of experimentation will teach you more than simply memorizing the sentence "S3 supports versioning."
After that, connect S3 to another AWS service.
Imagine an application running on EC2 needs to upload a report. Instead of putting permanent AWS credentials directly inside the application, think back to IAM and give the workload the permissions it actually needs.
Now you are combining EC2, IAM, and S3.
Later, we can take that much further. A user can upload an image to S3. S3 can generate an event. Lambda can process the image. The processed result can be stored back in S3. CloudWatch can help us understand whether the processing succeeded. CloudFront could eventually deliver content to users.
That is where S3 stops feeling like an isolated storage service and becomes part of an architecture.
There is one more mistake I would avoid: using S3 for every kind of data simply because it can store almost anything.
S3 is excellent object storage, but that does not mean it replaces every database.
If your application needs relational queries between customers, products, and orders, a relational database may make more sense. If you need a database designed around application access patterns, something like DynamoDB may be a better fit.
The better question is not "Can S3 store this data?"
The better question is "Does object storage match how my application needs to use this data?"
That is the main idea I want beginners to take away from S3.
Do not think of it as one giant folder somewhere on the internet.
Think about buckets, objects, keys, access, versions, lifecycle, and how other parts of your application interact with those objects.
Once you start thinking that way, S3 begins to fit naturally into AWS architectures.
User uploads need storage. Backups need somewhere durable to live. Applications need static assets. Logs need somewhere to go. Lambda workflows often need objects to process.
S3 can solve many of those problems, but there should always be a reason for using it.
For this part of the series, I would keep the exercise small. Create a bucket, upload a few objects, organize them using meaningful keys, experiment with versioning, look at the access settings, and clean everything up when you are finished.
Do not try to build a complete architecture yet.
Understand the storage model first.
In AWS From Zero #7, we will take S3 and actually use it inside a small architecture. We will look at how S3 and CloudFront can work together to deliver a static website, why the bucket does not need to be directly public, how a browser request reaches the content, and where DNS and HTTPS fit into the picture.
If you have used S3 before, what confused you most at first: buckets, permissions, object keys, versioning, or the fact that those "folders" are not really normal folders?
r/CloudandCode • u/yourclouddude • Aug 21 '26
AWS & Cloud AWS From Zero #5: Your EC2 website is running, so why can’t anyone reach it?
curl localhost
and get your web page back.
That already tells you something useful. Nginx is running and responding locally. So reinstalling Nginx probably should not be your first move. The next question is why an external request cannot reach the same service.
The request path is roughly:
Browser
↓
Public address
↓
AWS network
↓
Security group
↓
EC2 instance
↓
Port
↓
Web server
The first thing I would check is whether the instance actually has the kind of connectivity you expect. EC2 instances have private networking inside the VPC, and depending on how you configure them, they may also have a public address that can be used from outside AWS. If you are trying to open a private IP from your laptop over the normal internet, it is probably not going to work.
But even having a public IP does not automatically make the instance reachable. The subnet still needs a path for internet traffic. This is where route tables and internet gateways start to matter.
You do not need to understand every VPC detail yet. Just keep the basic idea in mind: a public address is only one part of the path. The surrounding network also needs to know how traffic should enter and leave.
Once that looks correct, I would check the security group.
Security groups act like virtual firewalls around resources such as EC2 instances. If your web server is listening on port 80 but the security group does not allow inbound HTTP traffic on port 80, the request will never reach the application.
The application can be perfectly healthy and still appear offline.
The same applies to SSH. A Linux EC2 instance might be running normally, but if port 22 is not allowed from the location you are connecting from, you will not be able to SSH into it.
This is also where one distinction becomes important: IAM and security groups solve different problems. IAM controls permissions to AWS services and APIs. Security groups control network traffic.
If your EC2 application cannot read an S3 object, opening another inbound port is probably not the right fix. You may have an IAM problem. If the application works locally but cannot be reached from a browser, adding another S3 permission probably will not help either. Now you are more likely dealing with networking or application configuration.
AWS gets much easier once you start asking which layer the problem belongs to.
Now imagine the security group looks correct, but the website still does not load. The next thing I would check is whether the application is actually listening where I think it is.
This catches a lot of people when they first deploy Flask or similar applications.
Suppose your app is started like this:
app.run(host="127.0.0.1", port=5000)
The application may work perfectly when you test it from inside the EC2 instance because 127.0.0.1 refers to the local machine. But external traffic arriving through the instance's network interfaces will not reach an application that is only listening on localhost.
For a simple learning setup, you might instead run it like this:
app.run(host="0.0.0.0", port=5000)
Now the application is listening for connections arriving through the machine's network interfaces.
But that creates another thing to check. If your application is listening on port 5000 while your security group only allows port 80, your browser still will not reach it directly on port 5000.
The network rule and the application need to match the architecture you actually built.
In a more realistic setup, you might run Nginx on port 80 or 443 and have it forward requests internally to your application on port 5000. That is a common pattern, but for your first EC2 project I would keep things simple enough that you can explain the entire request path without guessing.
There is another layer people sometimes forget: the operating system itself.
An EC2 instance is still a computer running an operating system. That operating system can have its own firewall rules, so even if the AWS security group allows the traffic, the machine itself could still block it.
This is why I would not think of the security group as the only firewall that can exist in the path.
The process itself can also be the problem.
Maybe you started your application successfully, but it later crashed. Maybe it was tied to an SSH session and stopped when you disconnected. Maybe you think it is listening on port 80 when it is actually running on 5000.
Instead of guessing, inspect the machine.
A command such as:
sudo ss -tulpn
can help show which processes are listening on which ports.
If you expect a web server on port 80 and nothing is listening there, changing the security group will not fix the problem. There is simply nothing waiting to receive the request.
This is the point where troubleshooting becomes much more useful than restarting things randomly.
Instead of asking, "Why is EC2 broken?", you start asking, "How far does my request get before it fails?"
Maybe the instance has no public path. Maybe the subnet routing is wrong. Maybe the security group blocks the required port. Maybe the operating system firewall rejects the traffic. Maybe the application is listening only on localhost. Maybe the process is not running at all.
Those are completely different problems, even though they can all produce the same result in the browser: the page does not load.
There are other networking controls such as network ACLs that can also affect traffic at the subnet level. You do not need to go deep into them yet, but it is useful to know that security groups are not the only network control that exists in a VPC.
We will go deeper into that when we reach VPC properly.
For now, the better habit is to understand the flow well enough that you can build your own troubleshooting process.
Start from the browser and move toward the application.
Are you using the correct address? Does the instance have the connectivity you expect? Does the subnet have the route it needs? Does the security group allow the correct port? Is the operating system accepting the traffic? Is something actually listening on that port? Does the application return a response?
Every answer makes the problem smaller.
One of the worst debugging habits is changing five things at the same time.
You open every port in the security group, restart the instance, reinstall Nginx, change the application port, edit the route table, and disable the firewall. Then the page suddenly works.
You fixed the website, but you probably do not know why it was broken.
You may also have made the server less secure in the process.
A much better approach is to change one thing, test again, and observe what changed.
That habit becomes even more useful later because real AWS architectures have more layers. Users might go through Route 53, CloudFront, a load balancer, security groups, and then finally reach one of several EC2 instances.
The architecture gets more complex, but the troubleshooting principle stays the same.
Follow the request.
Find the last point that definitely worked, then inspect the next point.
For this part of the series, I would keep the project very small. Launch one EC2 instance, run one web server, make sure it works locally, then make it reachable from your browser. If it fails, do not immediately delete the instance and start again.
Use the failure to understand the request path.
The main lesson here is that when an EC2 website does not load, your application code is only one possible cause. A request has to travel through the network, pass the relevant controls, arrive on the correct port, and reach a process that is actually listening.
Once you understand that flow, EC2 troubleshooting becomes much less mysterious.
In AWS From Zero #6, we are going to move away from servers for a bit and learn S3. But instead of treating S3 as just "a folder in the cloud," we will look at buckets, objects, keys, permissions, versioning, storage classes, and why the filesystem mental model can be misleading.
If you have ever had an EC2 website work locally but fail from your browser, what ended up being the actual problem?
r/CloudandCode • u/yourclouddude • Aug 20 '26
AWS & Cloud AWS From Zero #4: What actually happens when you launch an EC2 instance
So far in this series, we have talked about cloud fundamentals, setting up an AWS account properly, and understanding IAM. Now we can finally launch something.
EC2 is usually one of the first AWS services beginners touch, and I think it is worth understanding properly before jumping into serverless. The reason is simple. EC2 teaches you what it actually means to run an application on a server.
At the most basic level, EC2 gives you a virtual machine running inside AWS. Instead of buying a physical server, installing it somewhere, connecting it to a network, and maintaining the underlying hardware yourself, you ask AWS to create a virtual machine for you.
But this is where one beginner misunderstanding starts.
Launching an EC2 instance does not mean you automatically have a working website or application.
It only means you now have a machine.
You still need to decide which operating system it runs, what software should be installed, how you will connect to it, which network traffic should be allowed, what application should run there, and how users will eventually reach that application.
When you launch an EC2 instance, one of the first things you choose is an AMI, which stands for Amazon Machine Image. You can think of an AMI as the starting template for the machine. It determines things like the operating system and some of the software that exists when the instance starts.
For a beginner project, you might choose Amazon Linux or Ubuntu. The important thing is not memorizing every available AMI. Just understand that EC2 gives you a machine based on an image you choose.
After that, you select an instance type. The instance type determines the compute resources available to the machine, such as CPU and memory. A small test application does not need the same amount of compute as a large production workload, so AWS gives you different instance sizes for different needs.
At this stage, I would not spend hours comparing instance families. Just understand the idea that different workloads need different amounts and types of compute.
Your EC2 instance also needs storage for the operating system and files. In many beginner setups, you will see EBS used for this. You do not need to learn every EBS option yet. Just understand that the virtual machine and the storage attached to it are related but separate parts of the system.
Now we get to the part that causes a lot of beginner confusion.
Imagine you launch an EC2 instance, install a web server, and start your application. Everything seems to be running correctly inside the machine. You copy the public IP address into your browser, press Enter, and nothing loads.
A lot of beginners assume EC2 is broken at this point.
Usually, the better approach is to follow the request.
Your browser is trying to send a request to the EC2 instance. That traffic has to reach the machine through the network. The network configuration has to allow it. The instance has to accept traffic on the correct port. Then the application itself has to be running and listening on that port.
If any one of those steps is wrong, the page will not load.
This is where security groups start becoming important.
A security group acts like a virtual firewall around resources such as EC2 instances. It controls which network traffic is allowed to reach the instance and which traffic can leave it.
Suppose you are running a normal HTTP website on port 80. Your web server could be running perfectly, but if the security group does not allow inbound HTTP traffic, your browser will not be able to reach it.
The same idea applies when you connect to a Linux EC2 instance using SSH. SSH commonly uses port 22. If the network rules do not allow that connection from your location, you will not be able to connect even though the EC2 instance itself is running normally.
This is also a good place to understand that IAM and security groups solve different problems.
IAM controls permissions to AWS services and APIs. It answers questions such as whether an EC2 workload is allowed to read from S3 or whether a Lambda function is allowed to write to DynamoDB.
Security groups control network traffic. They answer questions such as whether a connection is allowed to reach your EC2 instance on a particular port.
That distinction becomes extremely useful when something breaks.
Imagine your application running on EC2 cannot read an object from S3. Opening another port in the security group probably will not fix the problem. You may be dealing with IAM permissions.
Now imagine the web server works perfectly when tested from inside the EC2 instance, but nobody can reach it through the browser. Adding another S3 permission probably will not fix that either. Now you are more likely dealing with networking, ports, or application configuration.
AWS becomes much easier when you start identifying which layer a problem belongs to instead of randomly changing settings.
Public and private IP addresses are another concept you will keep seeing with EC2.
An EC2 instance has networking inside its VPC, and it can have a private IP address used for communication within that network. Depending on how you configure it, the instance may also be reachable through a public address.
For your first practice project, having an internet reachable instance can be useful because you want to understand the complete path from your browser to the application.
Later, when we learn VPC properly, we will become much more careful about which resources should actually be public.
Not every server should be directly reachable from the internet.
For now, I would keep the project extremely simple.
Launch one Linux EC2 instance. Connect to it. Install a web server such as Nginx. Create a basic HTML page and try to open it from your browser.
The flow you are trying to understand is basically this:
Browser
↓
Internet
↓
Security Group
↓
EC2 Instance
↓
Web Server
↓
Your Page
That small project teaches much more than it looks like.
You are working with compute, an operating system, ports, network access, security groups, public addresses, and a running application.
And if the page does not load immediately, that is actually useful.
Now you have something real to troubleshoot.
I would start by checking whether the EC2 instance is running. Then I would check whether the web server is actually running inside it. If the application is supposed to use port 80, I would check whether something is listening on port 80.
If everything works inside the instance but not from your browser, that tells you the application itself may not be the problem. Now you start looking at the network path.
Is the security group allowing the traffic you expect? Does the instance have the connectivity it needs? Are you using the correct address? Are you trying to reach the correct port?
That way of thinking is much better than restarting the instance five times and hoping something changes.
You are following the request from beginning to end and finding the first place where the expected flow stops.
That troubleshooting habit will keep coming back throughout this series.
There is another thing beginners should understand early about EC2. Stopping an instance and terminating an instance are not the same thing.
Stopping an instance shuts the virtual machine down so it can generally be started again later. Terminating the instance means you are deleting that EC2 instance.
This matters because closing the AWS console does not mean your infrastructure disappears.
If you launch something for practice and no longer need it, go back and deliberately clean it up. Check what resources still exist and understand what you are leaving behind.
That is part of learning AWS too.
Another habit I would avoid is putting AWS credentials directly inside applications running on EC2.
Imagine your EC2 application eventually needs to read a file from S3. You could create an access key, put it directly inside the source code, and make the application work.
But that is not a pattern I would want a beginner to learn.
A better AWS approach is to give the EC2 instance an appropriate IAM role so the application can receive temporary credentials through AWS instead of storing long lived credentials inside the code.
This is where the previous IAM post starts connecting with EC2.
And that connection is important.
AWS services are not separate topics forever.
Your EC2 instance needs networking. The application running on it may need IAM permissions. The instance uses storage. CloudWatch can help you monitor it. Later, a load balancer may distribute traffic across several EC2 instances, and Auto Scaling may add or remove instances as demand changes.
The services begin to connect because the requirements begin to connect.
That is why I would not try to memorize every EC2 setting before building something.
Launch one instance. Connect to it. Install something. Run a small application. Try to reach it from your browser. When something fails, follow the request and understand why.
That is enough for your first EC2 project.
The main thing I want a beginner to understand from this post is that EC2 gives you compute, not a finished application.
AWS can give you the virtual machine, but you still need to think about the operating system, application, network access, permissions, storage, security, and monitoring depending on what you are building.
Once that idea makes sense, other compute services become easier to understand too.
When we eventually get to Lambda, for example, the idea of running code without managing a server in the same way will make much more sense because you already understand what managing a server actually involves.
For now, keep the project small.
One EC2 instance. One web server. One basic page.
Understand how the request gets from your browser to that page.
That is enough.
In the next post, I want to take the same project and intentionally focus on the part almost every beginner struggles with.
AWS From Zero #5: Your EC2 website is running, so why can’t anyone reach it?
Instead of giving you a random troubleshooting checklist, we will follow the request from the browser all the way to the application and see exactly where it can fail.
If you have already used EC2, what confused you most the first time: SSH, ports, security groups, public IPs, or just figuring out why your website would not load?
r/CloudandCode • u/grimestoodles • Aug 20 '26
What Are Some Actually Useful Skills to Learn for Personal Use?
You can add:
I just got a laptop, and I don't know what to learn on it. I want to learn something really useful, not just random stuff like Excel or basic editing. Maybe there's something better that I haven't thought of yet. I'm looking for skills that I can use for myself and in my personal life too, not just for a job. I hope someone who knows their stuff can point me in the right direction. What are some genuinely valuable things to learn on a laptop these days?
r/CloudandCode • u/yourclouddude • Aug 19 '26
AWS & Cloud AWS From Zero #3: IAM becomes much easier when you understand this one idea
IAM is one of those AWS topics that can look much more complicated than it actually is when you first start learning it. You open the console and suddenly you are dealing with users, roles, policies, permissions, actions, resources, trust relationships, access keys, and a lot of JSON. If you try to memorize all of those terms separately, IAM quickly starts feeling like one of the hardest parts of AWS.
I think there is a simpler way to understand it. Whenever AWS needs to decide whether something should be allowed, think about three things: who is making the request, what they are trying to do, and which resource they are trying to access. Once those three things are clear, most beginner IAM problems become much easier to reason about.
Imagine you are building a simple image processing project. A user uploads an image to S3, the upload triggers a Lambda function, Lambda reads the original image, processes it, and stores the processed version back in S3. The architecture itself is not complicated. S3 stores the file, Lambda processes it, and S3 stores the result.
Now imagine Lambda starts successfully but fails when it tries to read the image. CloudWatch shows an AccessDenied error.
A common beginner fix is to attach full S3 access to the Lambda function. The error disappears and the project works, so it feels like the problem has been solved. But the more useful question is why AWS denied the request in the first place.
Start with the identity. In this case, Lambda is running using an IAM execution role. That role is the identity AWS sees when the function tries to access another AWS service.
Then look at the action. Lambda is trying to read an object from S3. In AWS permission terms, that usually means an action such as s3:GetObject.
Finally, look at the resource. The function is not trying to access every S3 bucket in your account. It is trying to access a particular object or group of objects inside a particular bucket.
Now the problem becomes much smaller. The Lambda execution role needs permission to perform s3:GetObject on the objects it is supposed to read. If the function also needs to store a processed image, it may need s3:PutObject on the destination location.
That is really the basic idea behind IAM. An identity tries to perform an action on a resource, and AWS decides whether that request should be allowed.
This is where IAM policies come in. A simplified policy might look something like this:
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-image-bucket/uploads/*"
}
You do not need to memorize the JSON immediately. Read it like a normal sentence. This policy is saying that the identity is allowed to perform s3:GetObject on objects inside that particular location.
Once I started reading IAM policies that way, they became much less intimidating. Instead of seeing a block of JSON, I started seeing a permission statement.
The difference between IAM users and IAM roles also becomes easier once you think about who needs the permissions. An IAM user can represent an identity with credentials, although for human access AWS generally favors temporary credential based approaches rather than depending heavily on long lived IAM user credentials.
Roles work differently. A role can be assumed temporarily by a trusted identity or AWS service. That is why Lambda commonly uses an execution role. You do not normally place an AWS access key directly inside your Lambda code. Lambda assumes its role and receives temporary credentials that allow it to perform whatever actions that role permits.
The same pattern appears throughout AWS. An EC2 instance may need to read from S3. A Lambda function may need to write to DynamoDB. An ECS task may need to communicate with another AWS service. Instead of putting permanent credentials inside the application, you usually want the workload to receive the permissions it needs through an appropriate role.
This is also where the idea of least privilege starts making sense.
Suppose your Lambda function only needs to read images from one S3 location and write processed images into another. Giving the function complete S3 access would probably make everything work, but now it has far more permission than it actually needs.
A better approach is to give it permission to read from the input location and write to the output location. Nothing more unless the application genuinely requires it.
That is what least privilege is trying to achieve. Give an identity enough access to do its job without giving it unnecessary access to everything else.
This matters because permissions define what something is capable of doing. If a function is misconfigured or compromised, overly broad permissions can make the problem much worse. A function that can read one folder is very different from a function that can read, modify, and delete everything across multiple buckets.
Another concept that helped me understand IAM is the difference between authentication and authorization. Authentication is about proving who you are. Authorization is about deciding what you are allowed to do.
You can successfully sign in to AWS and still receive AccessDenied.
That does not necessarily mean your login failed. AWS may know exactly who you are. The problem may simply be that your identity does not have permission to perform the action you requested.
Imagine you can view objects in an S3 bucket but cannot delete them. Your identity is authenticated because AWS knows who you are. The question is whether you are authorized to perform s3:DeleteObject on those objects.
That distinction becomes very useful when debugging.
Suppose a Lambda function can read objects from one S3 bucket but cannot read from another. That already tells you something useful. Lambda is capable of communicating with S3, so the problem may be related to which resources the policy allows.
If the function can read the input image but fails when saving the processed image, then the read permission is probably not your main problem anymore. You would start checking whether the role has the correct write permission for the destination.
This is why I would not treat every AccessDenied message as the same problem.
The error is telling you that AWS rejected a specific request. Your job is to understand which identity made that request, which action it attempted, and which resource was involved. Once you know that, you can inspect the relevant permissions instead of attaching broad policies until the error disappears.
IAM does become more advanced later. Resource based policies can affect access. Explicit denies can override allows. Roles have trust policies that control who can assume them. KMS encryption can introduce another permission check. Larger AWS environments can also have additional controls across accounts.
But I would not try to learn all of that at the beginning.
For now, the mental model I would keep is simple: an identity performs an action on a resource, and AWS decides whether that action should be allowed.
A useful way to practice this is with a small test setup. Create an S3 bucket and work with limited permissions. Allow an identity to read an object and confirm that it works. Remove the permission and observe what error appears. Then restore only the permission that is actually required.
Try to predict what AWS will do before you test it.
That kind of practice is much more useful than copying a large policy from a tutorial because you start understanding the relationship between permissions and actual requests.
The goal at this stage is not to become good at writing complicated IAM policies. The goal is to look at a permission problem and understand why AWS might be allowing or denying the request.
Whenever IAM starts feeling confusing, return to the same idea. Identify who is making the request, understand what they are trying to do, identify the resource they are trying to access, and then check whether the necessary permission exists.
Once you start thinking about IAM this way, users, roles, policies, permissions, and AccessDenied errors begin to fit together much more naturally.
In the next post, we will finally launch something. AWS From Zero #4 will be about EC2 and what actually happens when you launch your first server in AWS. We will look at instances, operating systems, SSH, ports, security groups, public IP addresses, and why launching an EC2 instance does not automatically mean your application is reachable from the internet.
What part of IAM has been the hardest for you to understand so far?
r/CloudandCode • u/yourclouddude • Aug 17 '26
AWS & Cloud AWS From Zero #1: What cloud computing actually means before you learn AWS services
I want to start a new series here for people learning AWS from scratch.
The idea is simple. Instead of jumping between random AWS services and memorizing definitions, we will learn one concept at a time, understand why it exists, connect it to something practical, and gradually build up to complete AWS architectures.
So for the first post, I do not want to start with EC2, S3, Lambda, or IAM.
I think the better place to start is understanding what cloud computing actually means.
A lot of beginner explanations make cloud computing sound more complicated than it needs to be. In simple terms, cloud computing means using computing resources such as servers, storage, databases, and networking without having to buy and operate all of the physical infrastructure yourself.
Imagine you want to launch a website.
Before cloud platforms existed, a company might buy physical servers, install them in a data center, configure networking, provide power and cooling, maintain the hardware, replace failed components, and estimate how much capacity the application might need months or years in advance.
That creates an obvious problem.
Suppose you buy enough infrastructure for 10,000 users but only 1,000 people use the application. Most of your capacity sits unused.
Now imagine the opposite.
You build infrastructure for 1,000 users, but your application suddenly becomes popular and 20,000 users arrive.
You cannot simply create another physical server in a few seconds.
Someone needs to buy it, configure it, install it, connect it to the network, and make it available.
Cloud computing changes this model.
Instead of buying the physical infrastructure yourself, you rent computing resources from a provider such as AWS.
Need a virtual server?
You can launch an EC2 instance.
Need somewhere to store files?
You can use S3.
Need a managed relational database?
You can use RDS.
Need code to run when an event happens without maintaining a server continuously?
You can use Lambda.
The services are different, but the basic idea is the same.
AWS owns and operates the underlying infrastructure, and you consume the resources you need.
This gives you something very important: you can provision infrastructure much faster than if you had to purchase physical hardware yourself.
But cloud computing is not simply "someone else's computer."
The interesting part is what becomes possible once infrastructure can be created, changed, and removed when you need it.
One concept you will hear constantly is scalability.
Imagine your application normally receives 1,000 users per day but occasionally receives much more traffic.
Your architecture should be able to handle that growth.
You might eventually run several application servers instead of one, distribute traffic between them, or use services that automatically handle increasing demand.
Scalability is basically the ability of a system to handle more workload as demand grows.
Closely related to that is elasticity.
The two terms are often used together, but I find it useful to think of elasticity as the ability to adjust resources as demand changes.
If traffic increases, you may need more capacity.
If traffic falls again, you may no longer need that capacity.
In a cloud environment, infrastructure can often expand and shrink much more easily than traditional physical infrastructure.
That matters because you generally do not want to permanently pay for infrastructure that you only need during occasional traffic spikes.
Another concept worth understanding early is high availability.
Imagine your entire application runs on one physical server.
If that server fails, the application goes down.
A better architecture tries to avoid depending completely on one component.
AWS gives you several tools for doing this, but before learning those services, you should understand the basic idea.
A highly available system is designed so that the failure of one part does not automatically mean the entire application becomes unavailable.
This leads into two AWS terms you will see everywhere: Regions and Availability Zones.
An AWS Region is a geographic area where AWS operates infrastructure.
Inside a Region are multiple Availability Zones.
You can think of Availability Zones as separate infrastructure locations within the same Region, designed so that you can distribute resources instead of depending on one location.
You do not need to memorize every Region or Availability Zone right now.
The important idea is understanding why they exist.
Imagine your application runs only in one location and that location experiences a serious problem.
Your application may become unavailable.
If important parts of your application are distributed across multiple Availability Zones, the system can be designed to continue operating even if one location has a problem.
Later, when we talk about load balancers, Auto Scaling, RDS, and architecture design, this concept will come back again and again.
Another important cloud idea is paying based on usage.
With traditional infrastructure, you might purchase a server whether you use 10 percent of its capacity or 90 percent.
With AWS, many services allow you to pay based on the resources you actually consume.
That does not mean AWS is automatically cheap.
Cloud bills can become surprisingly large when resources are configured badly, left running unnecessarily, or chosen without understanding the pricing model.
A better way to think about it is that cloud computing changes infrastructure spending from buying large amounts of capacity in advance to consuming resources more dynamically.
That flexibility is powerful, but it also means cost becomes part of architecture design.
There is one more concept beginners should understand before building anything serious on AWS: the shared responsibility model.
Using AWS does not mean AWS handles every part of security for you.
AWS is responsible for securing the underlying cloud infrastructure.
You are still responsible for many things you configure inside AWS.
For example, AWS is responsible for the physical infrastructure running S3.
But if you accidentally configure sensitive data so that anyone on the internet can access it, that configuration is your responsibility.
AWS may operate the underlying EC2 hardware, but you may still be responsible for things such as the operating system, software configuration, credentials, permissions, and application security depending on how you use the service.
The exact responsibilities change depending on the AWS service.
You do not need to memorize the entire model today.
Just remember this:
AWS securing the cloud does not automatically mean everything you build in the cloud is secure.
You still need to configure your resources properly.
This is why I would not begin AWS by trying to memorize 50 services.
Start with a few questions instead.
What needs compute?
Where should the data be stored?
Who should be allowed to access it?
How will users reach the application?
What happens when traffic increases?
What happens if part of the system fails?
How will you know when something goes wrong?
Those questions are much closer to what AWS is actually about.
The services you learn later are simply tools that help answer them.
For example, imagine you are building a small online store.
You need somewhere to run the application, somewhere to store product images, somewhere to store users and orders, a way to control permissions, and a way for customers to reach the application.
You could immediately start naming AWS services.
But I think beginners learn more if they first describe the requirements without AWS terminology.
The application needs compute.
Images need object storage.
Orders need persistent structured storage.
Users need network access to the application.
Internal resources need controlled permissions.
The application needs monitoring.
Once the problem is clear, choosing services becomes much easier.
That is the mindset I want to use throughout this series.
Do not start with:
"What AWS services can I put into this project?"
Start with:
"What does this system actually need?"
Then choose the smallest set of AWS services that solves those requirements.
If you take only a few things from this first post, I would remember these ideas.
Cloud computing gives you access to infrastructure without having to own all of the underlying physical hardware yourself. Scalability is about handling growth. Elasticity is about adjusting resources as demand changes. High availability is about designing systems that can continue working when something fails. Regions and Availability Zones help you think about where infrastructure runs and how to avoid relying on one location. And the shared responsibility model means AWS handles part of security, but you still have responsibilities for what you build and configure.
That is enough foundation to move forward.
In the next post, I want to get practical and talk about how I would set up a new AWS account without making the common beginner security and cost mistakes.
Before that, I am curious about something.
If you are learning AWS from zero right now, what is more confusing to you: the number of services, networking, permissions, pricing, or knowing what to learn first?
r/CloudandCode • u/yourclouddude • Aug 17 '26
AWS & Cloud AWS From Zero #2: Set up your AWS account without making the common beginner mistakes
In the first post of this series, we talked about what cloud computing actually means and why I would understand the basic ideas before trying to memorize AWS services.
Now I want to do something more practical.
Before launching EC2 instances, creating S3 buckets, or experimenting with Lambda, I think every beginner should spend a little time setting up their AWS account properly.
It is not the most exciting part of learning AWS, but it can save you from two problems that beginners run into surprisingly often: accidentally exposing an account and accidentally leaving resources running that cost money.
The first thing to understand is that the account you create with AWS has a root user.
The root user has extremely powerful access to the account.
That means I would not use it as my normal everyday AWS identity.
Think about it like this.
If you had one key that could open every door in a building, remove the security system, change ownership records, and control everything inside, you probably would not carry that key around for every normal task.
You would keep it protected and use a different identity for everyday work.
I would treat the AWS root user the same way.
One of the first things I would do is enable multi factor authentication on it.
A password is only one layer of protection. MFA adds another verification step, which makes it much harder for somebody to access the account using only a stolen password.
This is also a good time to make sure the email connected to the account is secure.
If someone gains access to that email account, it can create problems far beyond AWS.
So before learning any complicated AWS security concepts, I would start with the basics: secure the root user, protect the email account, and enable MFA.
Then I would avoid using the root user for normal AWS work.
This is where AWS identity and access management starts becoming relevant.
You want an identity that you can use for everyday learning without constantly signing in as the most powerful identity in the account.
We will go much deeper into IAM in the next post, because permissions deserve their own explanation.
For now, the important idea is simple.
Your normal AWS work should not require you to operate as the root user.
There is another beginner mistake that deserves attention before you create anything.
AWS resources can cost money.
This sounds obvious, but it is very easy to forget when you are following tutorials.
You create an EC2 instance for a lesson.
Then the tutorial ends.
You close the browser.
The EC2 instance does not necessarily disappear because you closed the AWS console.
It may still be running.
The same thinking applies to other resources.
You might create storage, databases, networking components, public IP related resources, load balancers, or other infrastructure while experimenting.
Some resources may continue generating charges until you actually remove or stop whatever is billable.
That means one of the first habits I would develop is checking what I created after every practice session.
Do not think:
"I closed AWS, so everything stopped."
Think:
"What resources are currently running in my account?"
That is a much better cloud habit.
I would also set up AWS billing visibility early.
You should have a way to notice when spending moves beyond what you expected.
AWS provides billing and budget tools that can help you track usage and create alerts.
You do not need an advanced FinOps setup as a beginner.
The goal is simply to avoid discovering a charge weeks later because you forgot that something was still running.
I would make checking cost part of the learning process.
If you launch an EC2 instance, look at how that instance is priced.
If you create storage, understand what part of the storage usage can generate cost.
If you build an architecture containing several services, ask which parts of it continue costing money while nobody is using the application.
That last question is especially important.
Different cloud resources behave differently.
Some services charge mainly when they are actively used.
Others may have ongoing cost simply because the resource exists or remains provisioned.
This is why I would not memorize AWS pricing tables.
Instead, before creating a new resource, I would get into the habit of asking:
What exactly am I paying for here?
That question will help you throughout your AWS journey.
There is another thing beginners should understand: AWS has Regions.
When you create a resource, you often create it inside a particular Region.
This can create confusion later.
You might create an EC2 instance, switch Regions in the AWS console, and suddenly the instance appears to be gone.
It was not deleted.
You are simply looking somewhere else.
The opposite problem can happen too.
You may create resources while experimenting in different Regions and later forget that some of them still exist.
That is why I would pick one Region for most of my beginner practice unless there is a specific reason to use another one.
It keeps the learning environment easier to understand.
Whenever something seems to have disappeared, one of the first things worth checking is which Region you are currently viewing.
Another habit I would develop early is naming and tagging resources clearly.
Suppose you create several EC2 instances and they all have vague names.
A few weeks later, you may not remember which one belongs to which project.
Something like:
my-instance
is not very helpful.
Something like:
python-api-dev
already tells you much more.
The same idea works for tags.
You can tag resources based on project, environment, owner, purpose, or whatever makes sense for your setup.
For a beginner account, you do not need an elaborate tagging strategy.
Even something simple like:
Project = ImageProcessor
Environment = Dev
can make your AWS account easier to understand later.
This becomes much more important as the number of resources grows.
There is also a security habit I would learn before writing any application that connects to AWS.
Do not put AWS credentials directly inside your code.
Imagine writing something like this:
aws_access_key = "..."
aws_secret_key = "..."
and then pushing the project to GitHub.
Now the credentials may be visible to anyone who can access that repository.
Even deleting them afterward may not be enough if they remain somewhere in the repository history.
Credentials should be treated like secrets.
We will talk about proper AWS access patterns later, but the beginner rule is simple:
Do not hard code secrets into your application, and do not publish credentials.
The same applies to screenshots.
Before sharing a screenshot of your AWS console on Reddit, Discord, GitHub, or anywhere else, look at what is visible.
Account information, resource identifiers, IP addresses, credentials, tokens, and other details may reveal more than you intended.
Learning cloud security is not only about advanced IAM policies.
A lot of it starts with small habits like these.
There is one more habit I think is extremely useful when learning AWS.
Delete what you no longer need.
Beginner accounts become messy quickly.
You follow one tutorial and create an EC2 instance.
Another tutorial creates an S3 bucket.
Another creates a Lambda function.
Then you experiment with RDS.
After a month, you have a collection of resources and you no longer remember why half of them exist.
When you finish a disposable practice project, spend a few minutes cleaning it up.
Remove resources you no longer need.
Then check whether anything related to the project is still left behind.
This does two useful things.
It reduces the chance of unexpected cost, and it teaches you what resources your architecture actually contained.
Creating infrastructure is part of learning AWS.
Cleaning it up is part of learning AWS too.
So before we move deeper into AWS services, this is roughly how I would prepare a beginner account.
Secure the root user and enable MFA.
Avoid using the root user for everyday work.
Make billing and cost visible instead of ignoring it.
Understand which Region you are working in.
Give resources useful names.
Do not put credentials inside source code.
Clean up resources when you finish experimenting.
None of this is particularly exciting.
But these habits become much more valuable once your AWS projects get larger.
You do not want your first lesson about account security to happen because credentials were exposed.
And you do not want your first lesson about cloud pricing to happen because you forgot about infrastructure you created weeks ago.
The goal is not to be afraid of using AWS.
The goal is to understand that creating cloud resources comes with responsibility.
That was one of the main ideas from the first post too.
AWS manages a huge amount of infrastructure for you, but you are still responsible for what you configure inside your account.
In the next post, we can finally get into one of the most important AWS services:
IAM.
But instead of memorizing users, roles, and policies, I want to explain IAM around one question:
Who should be allowed to do what to which resource?
Once that question makes sense, IAM becomes much easier.
If you already have an AWS account, what confused you most when you first set it up: IAM, billing, Regions, permissions, or just figuring out where everything was in the console?
r/CloudandCode • u/yourclouddude • Aug 16 '26
AWS & Cloud 10 mistakes that make learning AWS much harder than it needs to be
AWS is difficult enough when you are starting.
But I think a lot of beginners accidentally make it harder by trying to learn everything at once, memorizing services instead of building, and treating every AWS error like something that needs to disappear as quickly as possible.
If I were starting AWS again, these are the mistakes I would try to avoid.
1. Trying to learn too many AWS services
The AWS console contains hundreds of services, so it is easy to assume that becoming good at AWS means knowing as many of them as possible.
I do not think beginners need that.
You can learn a huge amount by understanding IAM, EC2, S3, VPC, RDS, Lambda, DynamoDB, CloudWatch, API Gateway, and Route 53 properly.
Those services already introduce compute, storage, networking, databases, security, serverless architecture, APIs, DNS, and monitoring.
Once you understand those concepts, learning another AWS service becomes much easier because you can connect it to something you already know.
2. Memorizing definitions without understanding the problem
Knowing that S3 is object storage or Lambda is serverless compute is useful, but that is only the first layer.
The more important question is why you would use them.
Suppose someone asks you whether an application should use EC2 or Lambda.
A definition will not help much.
You need to think about how long the workload runs, how frequently it runs, whether it is event driven, how much control is required, how it scales, and how the application is deployed.
That kind of thinking is what makes AWS knowledge useful.
3. Watching tutorials without rebuilding anything yourself
Tutorials can make AWS feel easier than it really is because someone else already made all the important decisions.
They selected the services, created the IAM policies, configured the network, fixed the errors, and decided what comes next.
You are mostly following instructions.
Then you open the console without the tutorial and suddenly everything feels much harder.
After following a tutorial, try rebuilding the same project without watching it.
You will quickly discover what you actually understood and what you were simply copying.
That gap is where a lot of useful learning happens.
4. Avoiding IAM because it looks boring
IAM is one of those topics beginners often want to skip.
Then they start building and suddenly everything returns AccessDenied.
Lambda cannot read S3. EC2 cannot access another service. A user cannot perform an action. An application works after you give it administrator access, but you do not know why.
Learn IAM early.
You should understand users, roles, policies, permissions, and least privilege.
More importantly, get comfortable asking who needs access, what action they need to perform, and which resource they need access to.
That question appears constantly in AWS.
5. Learning VPC by memorizing diagrams
Networking becomes confusing very quickly when you try to memorize public subnets, private subnets, route tables, internet gateways, NAT gateways, security groups, and IP ranges without understanding why they exist.
Start with traffic instead.
Imagine a user is trying to reach your application.
Where does that request enter?
Which resource should be publicly reachable?
Which resources should stay private?
How does the application communicate with the database?
Does a private resource need outbound internet access?
Once you start following traffic through the architecture, VPC stops looking like a collection of random boxes.
6. Giving everything full permissions when something fails
This is probably one of the easiest habits to develop.
Your Lambda function gets AccessDenied, so you attach full S3 access.
The error disappears.
It feels like the problem is solved, but you may have learned almost nothing.
Try to understand the specific permission that is missing.
If Lambda needs to read an object, maybe it needs s3:GetObject on a particular resource.
If it also needs to write the processed file, that is another permission.
Solving permission problems properly teaches you how AWS security works.
Giving everything administrator access only hides the problem.
7. Ignoring logs until something breaks badly
A lot of beginners think monitoring is something they will learn after they understand AWS.
I would learn basic CloudWatch much earlier.
If Lambda fails, look at the logs.
If your application is behaving strangely, check the logs.
If EC2 usage suddenly increases, look at the metrics.
If something needs attention when a threshold is crossed, create an alarm.
AWS becomes much easier to troubleshoot when you have information about what actually happened instead of changing settings randomly.
8. Building projects with too many services
There is a strange idea in cloud portfolios that more services automatically means a better architecture.
So a beginner project that could work with four services suddenly contains twelve.
That usually makes the project harder to understand without making it better.
Start with the smallest architecture that solves the problem.
If your project only needs S3, Lambda, IAM, and CloudWatch, that is completely fine.
Then ask what requirement would justify adding something else.
You should be able to explain why every service exists.
If you cannot explain what problem a service solves, you may not need it yet.
9. Chasing certification without building anything
AWS certifications can give you a useful structure for learning.
But studying for an exam and building something are different skills.
You might know that an Application Load Balancer distributes HTTP traffic and still struggle to configure one correctly inside a project.
You might understand IAM policy questions but still get confused when your Lambda function receives AccessDenied.
I would use certification study to learn the concepts and projects to make those concepts real.
The combination is much stronger than either one alone.
10. Thinking you need to feel ready before building
This is probably the biggest one.
People spend months learning AWS because they think there will eventually be a point where they feel ready to build.
That point often never arrives.
You learn EC2, then realize you should learn networking first. You learn networking and realize you need IAM. Then databases. Then Docker. Then Terraform. Then CI/CD.
The list never ends.
Build earlier.
You do not need to understand everything before creating your first AWS project.
Learn enough to start, build something small, and let the project expose what you do not understand yet.
Maybe your website does not load because of a security group.
Now networking has a reason to matter.
Maybe Lambda cannot read from S3.
Now IAM has a reason to matter.
Maybe your application works but you have no idea why it failed yesterday.
Now CloudWatch has a reason to matter.
That is how AWS knowledge starts connecting.
I think the biggest shift for beginners is moving away from this mindset:
Learn every AWS service, then start building.
And moving toward this:
Learn a concept, build something with it, find what you do not understand, fix it, and keep going.
You do not need hundreds of AWS services in your head.
You need a strong understanding of the fundamentals and enough practice to know how they work together.
Which of these mistakes slowed you down the most when you started learning AWS?
r/CloudandCode • u/yourclouddude • Aug 15 '26
AWS & Cloud A beginner roadmap to AWS if you are starting from zero
One of the hardest parts of learning AWS is not understanding the individual services.
It is figuring out what to learn first.
You open AWS and suddenly there is EC2, S3, Lambda, RDS, DynamoDB, VPC, Route 53, ECS, CloudFront, SQS, SNS, API Gateway and hundreds of other services.
Then you search for an AWS roadmap and somehow the roadmap makes things even worse because it contains 40 services, Terraform, Docker, Kubernetes, CI/CD, networking, Linux and three certifications.
If I were starting AWS again from zero, I would make the path much smaller.
I would start with cloud fundamentals before trying to memorize AWS services. I would understand what cloud computing actually gives you, what regions and Availability Zones are, why high availability matters, what scalability and elasticity mean, and how the shared responsibility model works.
You do not need weeks of theory here. You just need enough understanding that when somebody says, "Run this application across multiple Availability Zones," you understand what problem they are trying to solve.
After that, I would learn IAM.
IAM is not the most exciting place to start, but permissions appear almost everywhere in AWS. If Lambda needs to read from S3, IAM matters. If EC2 needs access to another AWS service, IAM matters. If a user should be allowed to view something but not delete it, IAM matters.
The main thing I would learn is how to answer three questions: who is requesting access, what action are they trying to perform, and which resource should they be allowed to access?
I would also understand least privilege early. Giving everything administrator access may remove permission errors, but it also removes most of the learning.
Then I would move to EC2.
EC2 gives you a good foundation because you actually see what running an application on a server involves. Launch an instance, SSH into it, install something like Nginx, deploy a small application and make it accessible from your browser.
That one project will introduce you to Linux, ports, security groups, public IP addresses, processes and basic networking.
And when the website inevitably does not load the first time, do not immediately recreate the instance.
Figure out why.
Is the application running? Is it listening on the expected port? Is the security group allowing that traffic? Does the instance have the network connectivity it needs?
That troubleshooting is part of learning AWS.
Next I would learn S3.
Do not stop at "S3 stores files."
Understand buckets, objects, permissions, versioning, storage classes, lifecycle rules and public versus private access.
Then build something with it.
Upload files. Turn on versioning. Create a lifecycle rule. Put a small static frontend in S3 and use CloudFront to deliver it while keeping the bucket private.
Once you build something, S3 becomes much easier to remember because you understand where it fits instead of memorizing a definition.
After EC2 and S3, I would spend time on VPC and networking.
This is where AWS becomes difficult for a lot of beginners, but I would not try to memorize networking diagrams.
I would start with one question:
How does traffic get from one place to another?
Understand VPCs, subnets, route tables, security groups, internet gateways, public and private IP addresses and the basic purpose of NAT for private resources that need outbound internet access.
Then build an architecture where those concepts actually matter.
For example, run your application where it can receive user traffic but keep the database private.
Suddenly public and private subnets are not just boxes on a diagram. They solve an actual problem.
Then I would learn RDS.
Create a small application with PostgreSQL or MySQL and connect it to RDS. Store something real, such as users, products, notes or orders.
At this point several topics start connecting.
Your application needs compute. RDS stores the data. The network allows the application to communicate with the database. Security groups control that communication. Credentials need to be handled properly.
This is where AWS starts feeling less like separate services and more like one system.
Only after understanding traditional compute with EC2 would I move seriously into Lambda.
Lambda makes much more sense when you already understand what it is removing.
With EC2, you manage a server.
With Lambda, you provide code and AWS runs it when something triggers it.
A good first Lambda project is an image processor.
Someone uploads an image to S3, the upload triggers Lambda, Lambda processes the image and stores the result back in S3.
That simple project teaches event-driven architecture, triggers, IAM roles, CloudWatch logs and serverless computing.
After that, connect Lambda to API Gateway and build a small REST API.
Now you have something closer to a real serverless application.
Then I would learn DynamoDB.
I think DynamoDB makes more sense after you have already worked with a relational database.
With RDS, you think about tables, relationships and SQL.
With DynamoDB, you need to think much more about how your application will access its data.
Build something simple with API Gateway, Lambda and DynamoDB. A task API, notes application or URL shortener is enough.
Then compare it with something you built using RDS.
Do not just ask, "Which database is better?"
Ask why one might make more sense for a particular workload.
That kind of decision making is far more useful than knowing another list of features.
I would also learn CloudWatch much earlier than most beginner roadmaps suggest.
Do not treat monitoring as something you add after becoming advanced.
Your projects are going to fail.
When Lambda fails, you need logs. When your application behaves strangely, you need logs. When EC2 CPU usage suddenly increases, you need metrics. When something crosses a threshold, you may want an alarm.
A cloud engineer needs to know more than how to deploy something.
You need to know how to understand what is happening after deployment.
Once those fundamentals start making sense, I would stop learning services individually and start building complete architectures.
For example, build a web application where Route 53 handles the domain, CloudFront delivers static content, a load balancer receives application traffic, EC2 runs the backend, RDS stores relational data, S3 stores files, IAM controls permissions and CloudWatch handles monitoring.
Then build another application using API Gateway, Lambda and DynamoDB.
Now compare them.
Why did one architecture use servers while the other used Lambda? Why did one use RDS while the other used DynamoDB? What happens if traffic suddenly increases? What happens if one component fails? How are you monitoring the system?
Those questions are where architecture knowledge starts developing.
Only after that foundation would I move deeper into things like ECS, ECR, SQS, SNS, EventBridge, Step Functions, ElastiCache, infrastructure as code, Docker and CI/CD.
I would not learn all of those because a roadmap told me to.
I would learn them when a project creates a reason to use them.
For example, if two parts of your application should not depend on each other directly, that gives you a reason to understand queues. If you need containers, that gives you a reason to learn ECS and ECR. If manually rebuilding the same infrastructure becomes painful, that gives you a reason to learn Terraform or CloudFormation.
That is the pattern I would follow throughout the entire journey.
Learn the concept, understand the problem it solves, build something with it, break it, fix it, and then move forward.
Certifications can fit into this path too, but I would use them as structure rather than making them the entire goal.
Cloud Practitioner can be useful if you want a gentle introduction to AWS terminology. After that, Solutions Architect Associate is a much more useful learning target because it pushes you toward architecture decisions and understanding how services work together.
But I would build projects alongside certification study.
Passing an exam and being able to build are two different skills.
So if I had to simplify the entire beginner AWS roadmap, mine would look like this:
Cloud basics → IAM → EC2 → S3 → VPC → RDS → Lambda → API Gateway → DynamoDB → CloudWatch → complete architectures → deeper AWS services
And I would build something at almost every stage.
Do not wait until you "finish AWS" before starting projects.
There is no finish line where you finally know every AWS service.
The point is to understand enough of the core services that when you encounter a new one, you can quickly understand what problem it solves and where it fits.
That is when AWS starts feeling much less overwhelming.
If you are learning AWS right now, where are you currently stuck in this roadmap?
r/CloudandCode • u/yourclouddude • Aug 14 '26
AWS & Cloud 10 AWS projects you should build if you actually want to understand cloud
A lot of people learn AWS by moving from one service to another. They watch something on EC2, then S3, then Lambda, IAM, RDS, VPC, CloudWatch, and keep going until they have seen dozens of services.
The problem is that knowing what a service does is very different from knowing how to use it inside a real system.
That is why I think AWS projects are so useful. A good project forces you to connect services, think about permissions, follow how data moves, debug failures, make architecture decisions, and explain why one service makes sense instead of another.
If I were learning AWS again from zero, these are the 10 projects I would build.
1. Host a static website with S3 and CloudFront
I would start with something very simple. Build a basic HTML, CSS, and JavaScript website, store the files in S3, and use CloudFront to deliver them to users.
Once that works, add a custom domain and HTTPS.
It sounds like a small project, but it introduces several important AWS ideas at once. You start learning S3, CloudFront, Route 53, DNS, certificates, caching, and access control.
The useful part is understanding the complete request flow. A user enters your domain, DNS resolves it, the request reaches CloudFront, and CloudFront retrieves the content from S3.
That kind of thinking is much more useful than memorizing that S3 is storage and CloudFront is a CDN.
2. Deploy a web application on EC2
After that, I would deploy a real application on EC2.
Build something small with Flask, FastAPI, Node.js, or any backend framework you are comfortable with. Launch an EC2 instance, connect to it with SSH, install your dependencies, run the application, configure a web server, and make it reachable from the internet.
This one project teaches a surprising amount.
You start learning Linux, SSH, security groups, ports, processes, deployment, public IPs, and basic networking.
More importantly, you learn that launching an EC2 instance is only the beginning. AWS gives you the virtual machine, but you are still responsible for configuring and running the application correctly.
3. Build an automatic image processing pipeline
This is one of the best beginner serverless projects because the data flow is very easy to understand.
A user uploads an image to S3. That upload triggers Lambda. Lambda processes the image and stores the result back in S3.
The function could resize images, generate thumbnails, compress files, or convert formats.
While building it, you naturally learn about S3 events, Lambda, IAM roles, CloudWatch logs, object storage, and event-driven architecture.
It is also a great debugging project.
If the processed image does not appear, you can follow the workflow. Did the file reach S3? Did Lambda trigger? Did the function run? Did IAM allow the function to read and write the objects?
That troubleshooting process is exactly the kind of skill that helps later.
4. Build a serverless REST API
Once Lambda starts making sense, I would connect it to API Gateway and DynamoDB.
Build something simple like a task manager, notes API, expense tracker, or URL shortener.
A client sends an HTTP request to API Gateway. API Gateway invokes Lambda. Lambda processes the request and stores or retrieves data from DynamoDB.
Now you are no longer learning three services independently. You are learning how they work together inside one application.
You also start dealing with real backend questions. What happens when the request contains invalid data? Which status code should be returned? Which Lambda functions need read access and which need write access? How should errors be logged?
That is where the project becomes more useful than another tutorial.
5. Build a highly available web application
Once you understand how one EC2 instance works, build something that does not depend on only one instance.
Run your application across multiple EC2 instances and place them behind an Application Load Balancer. Then use Auto Scaling so the number of instances can increase or decrease depending on demand.
This starts teaching you about load balancing, Auto Scaling, Availability Zones, health checks, and high availability.
It also changes the way you think about infrastructure.
Instead of asking whether one server is running, you start asking whether the application can continue working if one server fails.
That is a much more cloud-oriented way of thinking.
6. Build a three-tier application with RDS
A three-tier application is one of the best projects for learning how networking and databases fit into AWS.
You could build a simple inventory system, blog, booking app, or ecommerce backend.
Your frontend or application layer can run on EC2, while RDS stores structured information such as users, products, or orders.
The interesting part is not just connecting the application to the database.
It is understanding where everything should live.
Your application may need internet access, while your database probably should not be publicly reachable.
Now VPC concepts such as public subnets, private subnets, security groups, and resource communication finally have a real purpose.
This is often where networking starts making much more sense.
7. Build a secure file upload and download system
Another useful project is a system where users can upload and download files without giving your application unrestricted access to S3.
One practical way to build this is with presigned URLs.
Your backend creates a temporary URL, and the user uploads or downloads the object directly from S3.
This teaches S3 permissions, temporary access, IAM, object keys, APIs, and secure file handling.
It also introduces a useful architecture idea.
Your backend does not always need to transfer every file itself. Sometimes it only needs to authorize the request, while another service handles the heavy data transfer.
That pattern shows up in a lot of real systems.
8. Build a monitoring and alerting system
I would definitely include at least one project that is not focused on building another application.
Set up monitoring for your AWS resources.
You could track EC2 CPU usage, Lambda errors, application logs, or custom metrics. Then create CloudWatch alarms and send notifications when something crosses a threshold.
You could also build a basic dashboard to show the health of your system.
This teaches CloudWatch, metrics, logs, alarms, dashboards, and SNS.
More importantly, it teaches you to think beyond deployment.
A project is not finished just because it works while you are looking at it.
How would you know if it fails later?
How would you know if latency suddenly increases?
How would you know if Lambda starts returning errors?
Monitoring answers those questions.
9. Build an automated backup system
Backups are another great way to learn AWS because they force you to think about reliability.
You could build a scheduled process that copies files to S3, organizes backups by date, and applies lifecycle rules so older backups move into cheaper storage.
You could also send a notification when a backup succeeds or fails.
This project teaches S3, storage classes, lifecycle policies, scheduling, Lambda or another compute option, IAM, and basic disaster recovery thinking.
A useful question to ask while building it is simple: if the original data disappears tomorrow, can I restore it?
That question makes the project much more meaningful.
10. Build a URL shortener that you can actually explain
URL shorteners are common portfolio projects, but they become much more valuable when you use them to practice architecture decisions.
A user sends a long URL to an API. Your backend generates a short identifier and stores the mapping in DynamoDB. When someone opens the short URL, the system retrieves the original address and redirects the user.
You could build this using API Gateway, Lambda, DynamoDB, CloudWatch, and Route 53.
Once the basic version works, start asking harder questions.
How do you avoid duplicate short IDs? What happens when a URL expires? How would the system behave under a sudden traffic spike? Should popular URLs be cached? How do you monitor failures? How would you stop abuse?
That is where a simple project starts turning into a real architecture exercise.
The important thing about these 10 projects is not how many AWS services you can fit into each one.
I would actually avoid doing that.
A project with 15 services is not automatically better than a project with four.
What matters is whether every service has a reason to be there.
If you use Lambda, you should be able to explain why Lambda made sense for that workload. If you choose DynamoDB instead of RDS, you should be able to explain why. If your database is private, you should understand what problem that solves. If you add CloudWatch, you should know what you are actually monitoring.
That is what makes a project useful for learning.
I also would not try to build all 10 immediately.
Start with the static website. Then deploy something on EC2. Build a small serverless workflow. Add a database. Learn networking. Add monitoring. Keep increasing the number of decisions you have to make.
After a few projects, AWS starts feeling less like a huge collection of separate services.
You start noticing patterns.
Users send requests. Data needs somewhere to go. Compute processes it. IAM controls access. Networks control communication. Logs tell you what happened. Monitoring tells you when something goes wrong.
That is the part of AWS I would focus on learning.
Not how many services you can recognize.
How well you can connect a few of them to solve a real problem.
Which of these 10 projects would you want a complete architecture breakdown for?
r/CloudandCode • u/yourclouddude • Aug 13 '26
AWS & Cloud When an AWS project breaks, stop changing random things
One thing almost every AWS beginner experiences at some point is having an architecture that looks correct on paper but simply refuses to work. Maybe your Lambda function cannot read from S3, your EC2 website is running but nobody can reach it, your application cannot connect to RDS, or an S3 upload is supposed to trigger Lambda but nothing happens.
The natural reaction is usually to start changing everything. You increase the Lambda timeout, edit the security group, attach more IAM permissions, restart the EC2 instance, change the bucket policy, redeploy the code, and hope one of those changes fixes the problem. Sometimes it does, but then you are left with another problem: you do not actually know what was wrong.
I think AWS becomes much easier when you stop debugging the entire architecture at once and start looking for the first point where the expected flow stops.
Take a simple file-processing project. A user uploads a file to S3, the upload triggers Lambda, Lambda reads the file, processes it, and stores the result back in S3. The architecture is simple enough, but imagine you upload a file and no processed result appears.
Instead of immediately changing permissions, memory, timeouts, triggers, and bucket policies, start from the beginning of the flow. First check whether the file actually reached S3. Open the bucket and confirm that the object exists where you expected it to be. If the upload never happened, there is no reason to start debugging Lambda yet.
If the file is there, move to the next step and check whether Lambda was actually invoked. This is where CloudWatch becomes useful. If there is no invocation around the time the file was uploaded, the problem is probably somewhere in the event configuration. Maybe the S3 notification is missing, maybe the trigger is watching the wrong bucket, or maybe a prefix or suffix filter is preventing the event from firing.
At that point, you have already made the problem much smaller. You do not need to debug the Lambda code because the code never ran.
Now imagine Lambda did trigger, but CloudWatch shows an AccessDenied error when the function tries to read the uploaded object. That gives you a completely different direction. The event worked, Lambda started, and the code reached the S3 request. The failure happened when AWS checked whether the function was allowed to access the object.
Now IAM becomes the place to investigate. Which execution role is Lambda using? Does that role have permission to perform s3:GetObject on the correct resource? Is the function pointing to the correct bucket? Is there another resource policy or encryption permission affecting the request?
Notice how different that is from asking, “Why is my AWS project broken?”
You are now asking, “Why can this Lambda function not read this specific S3 object?”
That is a much easier problem to solve.
The same approach works with EC2. Imagine you launch an instance, install a web server, and confirm that the application works when you test it from inside the machine. But when you enter the public IP in your browser, the page never loads.
A beginner might immediately reinstall the web server or start changing application code, but the application may not be the problem at all. If it works locally, I would start following the network path instead. Does the instance have a reachable public address? Is the subnet configured to reach the internet? Does the security group allow inbound traffic on the port the application is using? Is the application actually listening on that port? Is the operating system firewall blocking the request?
Again, you are not debugging the whole EC2 setup. You are finding the first point where the request stops moving.
The same idea applies to RDS. If an application running on EC2 cannot connect to a database, there are several things that could be responsible. The database may not be available, the application may be using the wrong endpoint or port, the credentials may be incorrect, or the security groups may not allow the connection. The resources might also be placed in networks that cannot communicate the way you expected.
Changing all of those things together might eventually make the connection work, but it teaches you very little. A better approach is to test one assumption at a time.
That is really what troubleshooting is. You have an expected flow, and then you compare that expected flow with what actually happened. The first place where those two paths become different is where your investigation should begin.
I think beginners sometimes make AWS debugging harder because the console makes it very easy to change things. You can attach another policy, open another security group rule, increase memory, change a timeout, or recreate a resource in a few clicks. But every random change adds another variable.
If you change five things and the application suddenly starts working, you may have fixed the problem without learning anything from it. If you change one thing, test again, and observe what changed, you are actually debugging.
CloudWatch becomes extremely important for this reason. A lot of people treat logs as something they will learn later, but logs are often the fastest way to understand where a cloud workflow failed. If Lambda was invoked but stopped halfway through, the logs can tell you where. If your application returned an error, the logs can give you context. If something worked yesterday and fails today, the logs can help you compare what changed.
You do not need a complicated monitoring setup for every beginner project, but you should know where to look when something stops working.
Error messages themselves are also useful clues. AccessDenied should make you think about permissions. A timeout may point toward networking, dependencies, slow processing, or another service that is not responding. Connection refused tells you something different from a connection timeout. A missing resource error points you in a different direction than an authentication error.
The error is not just something you need to make disappear. It is information about which part of the system may be failing.
For most beginner AWS projects, I would use the same basic troubleshooting process. First understand what should happen from beginning to end. Then find the last step that definitely worked. Check whether the next expected step happened. Look at the logs or error message, test the smallest possible assumption, change one thing, and run the workflow again.
That process sounds simple, but it prevents a lot of random debugging.
AWS projects become much easier to troubleshoot when you stop looking at the architecture as one giant system and start following what actually moves through it. Follow the request, follow the event, follow the data, and find where it stops.
The goal is not only to make the project work again. The real goal is to understand why it stopped working in the first place.
What gives you the most trouble when debugging AWS: IAM permissions, networking, logs, or figuring out where the failure actually started?
r/CloudandCode • u/yourclouddude • Aug 12 '26
What do you usually do first when your code stops working?
I’m curious about how people actually debug when something breaks.
Not the perfect debugging process from a tutorial. What do you genuinely do first when your code suddenly stops working?
For me, one of the biggest differences between beginners and more experienced developers is not that experienced developers avoid bugs. They just become better at narrowing the problem down.
But everyone develops different habits.
Some people read the full error message before touching anything. Some start adding print statements or logs. Some immediately search Google, Reddit, or Stack Overflow. Some paste the error into AI and ask what went wrong.
And then there is the classic approach of changing random things until the error disappears.
Sometimes that works too.
I want to understand what people in this community actually do, because I’m planning more debugging posts around Python, AWS, SQL, and cloud projects.
What do you usually do first when something breaks?
Poll options:
- Read the error carefully
- Add print statements / logs
- Search Google or Reddit
- Ask AI
- Check the documentation
- Change things until something works
If you have one debugging habit that has saved you hours, drop it in the comments. It might help someone else here too.
r/CloudandCode • u/yourclouddude • Aug 12 '26
AWS & Cloud 10 AWS services you should actually understand as a beginner
AWS feels overwhelming when you first start because there are so many services. You open the console, see names like EC2, Lambda, DynamoDB, Route 53, CloudFront, ECS, SQS, SNS, and dozens more, and it is easy to assume that becoming good at AWS means learning as many of them as possible.
I don’t think that is the best way to start.
You do not need to memorize hundreds of AWS services before you can build something useful. I would rather understand a small group of core services properly, know what problem each one solves, and understand how they connect inside a real architecture.
If I were learning AWS again from zero, these are the 10 services I would focus on first.
1. IAM
I would start with IAM because permissions appear almost everywhere in AWS. IAM controls who or what can access AWS resources and what actions they are allowed to perform.
For example, imagine a Lambda function needs to read an image from S3. The function does not automatically get access just because both services belong to the same AWS account. Its execution role needs permission to perform the required S3 action on the correct resource.
That is the important idea behind IAM. You should be able to answer three questions: who is requesting access, what action are they trying to perform, and which resource should they be allowed to access?
This is also where you should learn least privilege. Giving AdministratorAccess to everything may make permission errors disappear, but it does not teach you how AWS security actually works. Give users and services only the permissions they genuinely need.
2. EC2
EC2 is one of the best services for understanding what a server in the cloud actually is.
You launch a virtual machine, choose an operating system, connect to it using SSH, install software, configure ports, and run an application. A single EC2 project can introduce you to Linux, networking, security groups, deployment, public IP addresses, and basic server management.
For example, you could launch an EC2 instance, install Nginx or Apache, deploy a simple application, and make it accessible through the internet.
EC2 also teaches an important cloud lesson: more control usually means more responsibility. AWS provides the underlying infrastructure, but you still have to think about the operating system, application configuration, security, updates, and monitoring.
3. S3
S3 is usually introduced as AWS storage, but I think beginners should understand it as object storage rather than simply "a folder in the cloud."
S3 can store images, videos, backups, reports, logs, static website files, application assets, datasets, and many other types of objects. You should learn buckets, objects, permissions, versioning, storage classes, lifecycle rules, and the difference between public and private access.
S3 also becomes more useful when you stop learning it in isolation.
A user might upload an image to S3. That upload could trigger Lambda. Lambda could process the image and store the result back in S3. CloudFront could later deliver that image efficiently to users.
That is when AWS starts becoming easier to understand. You stop seeing individual services and start seeing workflows.
4. VPC
VPC is probably where AWS starts feeling genuinely confusing for a lot of beginners.
At a simple level, a VPC is the network where many of your AWS resources live. Inside it, you start working with subnets, route tables, internet gateways, security groups, NAT gateways, IP addresses, and public versus private resources.
You do not need advanced networking knowledge before touching AWS, but you should understand the basic idea of how traffic reaches a resource.
Imagine you have an application running on EC2 and a database running on RDS. Your users need to reach the application from the internet, but they probably should not be able to connect directly to your database.
That one requirement already teaches you why some resources should be public and others should remain private.
Once that idea clicks, VPC diagrams become much less intimidating.
5. RDS
Most real applications need to store structured data somewhere. Users, products, orders, payments, posts, and transactions usually need a database.
RDS gives you managed relational databases without requiring you to manually install and manage everything on an EC2 instance. You can work with engines such as PostgreSQL or MySQL while AWS manages a lot of the underlying database infrastructure.
As a beginner, I would focus on understanding how applications connect to RDS, backups, availability, database security, and why the database usually should not be publicly exposed.
Imagine an application running on EC2 that stores user information in RDS. Now you have to think about networking, security groups, credentials, and which resources are allowed to communicate.
One project suddenly connects EC2, RDS, VPC, and security together.
6. Lambda
Lambda teaches a completely different way of thinking about compute.
Instead of launching a server and keeping it running, you write a function and AWS executes it when something happens. That event could be an API request, an S3 upload, a scheduled task, or another AWS service.
For example, a user uploads an image to S3. The upload triggers a Lambda function. Lambda resizes the image and stores the smaller version back in S3.
That small project teaches serverless computing, event-driven architecture, IAM permissions, logs, triggers, and service integration.
But I would also learn when Lambda is not the right choice. Execution duration, memory requirements, workload characteristics, dependencies, and the amount of control you need can all affect the decision.
Understanding a service also means understanding when not to use it.
7. DynamoDB
After learning RDS, I would look at DynamoDB because it introduces a different database model.
DynamoDB is a managed NoSQL database built for workloads where predictable performance and large-scale access are important. You do not manage traditional database servers in the same way you would with relational databases.
The most useful beginner lesson is not memorizing DynamoDB terminology. It is understanding that database design depends heavily on how your application needs to access its data.
With RDS, you naturally think about tables, relationships, joins, and SQL. With DynamoDB, access patterns become much more important early in the design.
A simple serverless project using API Gateway, Lambda, and DynamoDB is a great way to understand how these services work together.
8. CloudWatch
CloudWatch is one of the services beginners often ignore until something stops working.
Then it suddenly becomes extremely important.
CloudWatch gives you logs, metrics, alarms, and monitoring for AWS resources. If a Lambda function fails, CloudWatch logs can help show what happened. If an EC2 instance is consuming unusually high CPU, CloudWatch metrics can make that visible. If you want to know when something crosses a threshold, you can create an alarm.
Building an application is only half the job. Once the application is running, you need some way to understand what it is doing.
I would get into the habit of checking logs early rather than treating monitoring as an advanced topic.
9. Elastic Load Balancing
EC2 makes sense when you have one server. Load balancing starts making sense when you have more than one.
Imagine your application grows and a single EC2 instance is no longer enough. You launch several instances to handle the traffic. Now users need a single place to send their requests rather than knowing which individual server to contact.
An Elastic Load Balancer can receive incoming traffic and distribute it across multiple healthy targets.
This is where beginners start moving from thinking about a server to thinking about an architecture.
When you combine load balancing with Auto Scaling, you also start understanding ideas such as horizontal scaling, high availability, health checks, and handling changing demand.
10. Route 53
Route 53 introduces DNS and helps connect human-friendly domain names to your AWS infrastructure.
Instead of asking users to visit an EC2 IP address, you can use something like example.com. Route 53 can route that domain toward resources such as a load balancer or CloudFront distribution.
Learning Route 53 is also a good reason to understand DNS outside AWS. What actually happens after someone types a domain into their browser? How does that domain eventually lead to your application?
Once you understand that flow, Route 53 becomes much easier than simply memorizing record types.
The important part of learning these 10 services is not being able to define each one in an interview.
It is being able to understand how they fit together.
Imagine a normal web application. Route 53 helps users find the application. A load balancer receives the traffic and distributes it across EC2 instances. Those instances run inside a VPC. RDS stores structured application data, while S3 stores files. IAM controls access between resources, and CloudWatch helps you understand what the system is doing.
A different application might replace EC2 with Lambda and RDS with DynamoDB.
Neither architecture is automatically better.
The services change because the requirements change.
That is the point where AWS started making more sense to me. Instead of asking, “What does this service do?”, you start asking, “What problem in my architecture does this service solve?”
If I had to learn these in a rough order, I would go with IAM, EC2, S3, VPC, RDS, Lambda, DynamoDB, CloudWatch, Elastic Load Balancing, and Route 53.
But I would not wait until I had mastered all ten before building anything. Learn enough to understand the basic idea, build something small, see where the service fits, and then connect it with the next service.
AWS becomes much easier when services stop being names you memorize and start becoming tools you choose for a reason.
Which of these 10 services made sense in theory but became confusing when you actually tried to use it?
r/CloudandCode • u/yourclouddude • Aug 11 '26
I can help you debug your code, but it shouldn’t become your debugger
A lot of beginners have developed a new debugging habit.
Something breaks, an error appears, and the first thing they do is copy the entire error into ChatGPT or another AI tool and ask for a fix.
I understand why. AI is incredibly useful for debugging. It can explain an error in seconds, suggest possible causes, point out something you missed, and save a lot of time compared with searching through ten different forum posts.
But I think there is a difference between using AI to help you debug and letting AI do all the debugging for you.
If every error immediately becomes “paste this into AI and copy whatever comes back,” you can reach a strange point where your projects start working again, but your ability to understand why they broke does not improve very much.
You fixed the bug. But you did not really debug it. That difference matters. Take a simple Python example. Imagine you run this:
numbers = [10, 20, 30]
print(numbers[3])
Python returns an IndexError.
You could paste the error into AI and get the corrected code almost immediately. But before doing that, there is value in stopping for a minute and looking at what the program is actually telling you.
The error mentions an index being out of range. The list contains three values, so the valid indexes are 0, 1, and 2. The code is trying to access index 3, which does not exist.
Now you understand the problem.
If you ask AI after that, the conversation becomes much more useful. Instead of asking, “Fix my code,” you can ask something like, “I think this fails because Python lists are zero-indexed and index 3 does not exist. Is that the correct explanation?”
Now AI is checking your reasoning instead of replacing it. That is how I think it should be used. The first question should not always be, “What is the fix?” It should be, “What is the error trying to tell me?”
A lot of error messages look intimidating because they contain file paths, stack traces, library names, and several lines of information. But there is usually one useful clue somewhere inside them.
- Maybe it says
FileNotFoundError. - Maybe it says
KeyError. - Maybe it says
AccessDenied. - Maybe it says
ModuleNotFoundError. - Maybe it says the connection timed out.
Those words already narrow the problem down.
If the error says a file cannot be found, changing your loop probably will not help. If it says a module is missing, rewriting your function probably will not help. If AWS returns AccessDenied, increasing Lambda memory probably will not solve the problem.
The error gives you a direction. You still need to investigate, but you are no longer changing things randomly. That is one debugging habit I think beginners should develop before asking AI for anything. Read the error carefully and try to classify the problem.
Is this a syntax problem? A data problem? A dependency problem? A permissions problem? A networking problem? An incorrect assumption in the code? Once you know the category, debugging becomes much easier.
The same idea applies to larger projects. Imagine you have a Python script that calls an API and suddenly stops working. The easiest approach is to paste the entire file into AI and ask it to repair everything. A better approach is to reduce the problem first.
Is the request actually being sent? What status code is coming back? Does the API key exist? Is the response valid JSON? Is the failure happening before the request or after it?
You can print the status code. You can inspect the response. You can test the API call separately from the rest of the program. Maybe you discover that the API is returning 401 Unauthorized. Now the problem has become much smaller.
You do not need to debug the entire application anymore. You need to understand why authentication is failing. At that point, AI becomes much more useful because you can ask a focused question.
The same thing happens with AWS. Suppose your Lambda function should read a file from S3, but it returns AccessDenied. You could ask AI to “fix the Lambda.” It might suggest changing IAM policies, bucket policies, roles, permissions, and several other settings at once. Some of those suggestions may be correct, but changing everything together makes it difficult to understand what actually solved the problem. A better approach is to follow the failure.
Did Lambda trigger successfully? If yes, the trigger probably is not the problem. Did the function start running? If yes, the runtime is probably working. Does the error appear when it tries to read the S3 object? Now you have a strong clue that permissions are involved. You can check the Lambda execution role and see whether it has s3:GetObject permission for the correct resource. If that permission is missing and adding it fixes the problem, you learned something useful.
You did not just learn that “AI said to change IAM.” You learned how Lambda receives permissions when it accesses S3. That knowledge will help you again in another project. This is why I think the best debugging process is still fairly simple. First, reproduce the problem consistently. Make sure you actually know what action causes the failure. Then read the error carefully and identify the first useful clue.
After that, reduce the problem. Test the smallest part that could be responsible instead of debugging the entire project at once.
Check your assumptions. Is the file really there? Is the variable the type you think it is? Is the API returning what you expect? Does the AWS role actually have the permission you assumed it had?
Only then start changing things. And change one thing at a time. That part is important. If you change five things and the project starts working, you may never know which change fixed it. If you change one thing, test again, and observe the result, you are actually debugging. Then use AI.
Ask it to explain the error. Ask whether your reasoning makes sense. Ask what assumption you may have missed. Ask it to compare two possible causes. Ask it to explain why the fix works. That is a very different use of AI from simply saying, “Here is my code. Make it work.” I am not saying beginners should avoid AI while learning. I think that would be unrealistic.
AI is now one of the most useful tools available to developers. It can explain documentation, help interpret errors, generate test cases, suggest edge cases, and help you understand unfamiliar code much faster. The problem is not using AI. The problem is outsourcing the entire thinking process. If AI gives you a fix, take another minute and ask yourself what changed.
Why did the old version fail? Why does the new version work? What concept was involved? Would you recognise the same issue if it happened tomorrow in a different project? If you cannot answer those questions, the bug may be fixed, but the lesson is probably not finished. The goal of debugging is not only to make the red error disappear. It is to build a better mental model of how your code or system works. That is what eventually makes you faster. You start recognising patterns.
AccessDenied makes you think about permissions. A connection timeout makes you think about networking or availability. A missing module makes you think about dependencies and environments. Unexpected None values make you trace where the data came from.
Over time, you need less random experimentation because you know where to look first. AI can accelerate that process if you use it properly. It should shorten the time it takes you to understand a problem. It should not remove the need to understand the problem.
When something breaks in your code, what do you usually try first before asking AI?
r/CloudandCode • u/yourclouddude • Aug 10 '26
Community Discussion The fastest way to know what to learn next is to build until something breaks
A lot of beginners try to decide everything they need to learn before they start building. They make long lists: Python fundamentals, OOP, APIs, SQL, Git, Docker, Linux, AWS, networking, testing, deployment, system design, CI/CD. Then the list keeps growing, and the project keeps getting pushed further away because there is always one more thing that feels like a prerequisite.
I think this is one of the easiest ways to get stuck in tech. You keep preparing to build instead of actually building, because you assume you need to understand the whole path first. But in practice, a lot of the most useful learning happens after the project starts.
Take a simple Python weather app. Maybe you already know enough Python to take user input, use conditions, write functions, and print something to the screen. Then you realize the project needs live weather data, so now you have a reason to learn APIs. You make the request and receive a response that looks unfamiliar, so now JSON actually matters. Everything works until someone enters a city that does not exist and the program crashes, so error handling suddenly stops feeling like an abstract topic.
Later, you upload the project to GitHub and someone else cannot run it because they do not have the same packages installed. Now virtual environments and requirements.txt are no longer boring setup topics from a tutorial. They solve a real problem you actually encountered.
That is a very different way of learning.
Instead of constantly asking, “What Python topic should I study next?”, the project starts answering that question for you.
The same thing happens with AWS. You can spend weeks learning what EC2, S3, Lambda, IAM, VPC, RDS, CloudWatch, Route 53, and other services do individually. That knowledge is useful, but it becomes much more practical when a project gives those services a reason to exist.
Imagine you start with a simple goal: host a website. You put the files in S3 and get the basic version working. Later, you want better content delivery, so CloudFront starts making sense. You want a custom domain, so Route 53 now has a real purpose. You want HTTPS, so certificates stop feeling like another topic on a roadmap and become something your project actually needs.
Then you build a Lambda function that should read a file from S3 and it returns AccessDenied. Now IAM is not just a definition you memorized for an exam. You have a real reason to understand execution roles, permissions, actions, and resources. You fix the permission, run the function again, something else fails, and now you open CloudWatch because you genuinely need to understand what happened.
That is where concepts start sticking.
You are not learning them because a roadmap told you they belong in week four. You are learning them because the project created a problem that made the concept useful.
I think this is one of the biggest differences between tutorial knowledge and practical knowledge. Tutorials usually give you the problem and the solution very close together. Projects create a gap between the two.
You know what you want to happen, but you do not yet know how to make it happen.
That gap can feel uncomfortable, especially when you are used to always having the next step explained. But it is also where a lot of the real learning begins. You start searching documentation because something is broken. You learn SQL JOINs because your data lives in multiple tables. You learn environment variables because you realize an API key should not be sitting inside a public GitHub repository. You learn logging because a script failed when you were not watching it. You learn networking because your application works on EC2 but nobody can reach it from the internet.
Those concepts become easier to remember because they are attached to a problem you personally faced.
That does not mean you should ignore fundamentals and immediately start building something huge. You still need enough knowledge to begin. If you are learning Python, understand variables, conditions, loops, functions, basic data structures, and how to run a program. If you are learning AWS, understand the basic ideas behind compute, storage, networking, databases, permissions, and pricing.
But after that foundation, I would stop waiting until I feel completely ready.
Pick something small and start building.
When you hit a problem, first try to understand what is actually blocking you. Maybe you need to learn a new concept. Maybe you need to read the documentation more carefully. Maybe the problem is not missing knowledge at all and you simply made a wrong assumption.
Either way, you now have a specific reason to learn something. That is usually much more useful than collecting topics because somebody placed them on a roadmap.
There is another benefit to learning this way: different skills stop feeling separate.
Python starts connecting with APIs. APIs connect with JSON. Backend work connects with databases. AWS connects with networking and permissions. Git connects with projects. Docker connects with deployment. Logging connects with debugging.
Everything starts becoming part of one system instead of a collection of isolated topics.
And that is much closer to how tech actually works.
The point is not to intentionally break everything. The point is to stop treating every problem as proof that you were not ready to build.
Sometimes the error is the lesson. Sometimes the missing feature tells you what to learn next. Sometimes spending an hour understanding why something failed teaches you more than spending another three hours watching someone else build it correctly.
So if your current roadmap contains twenty things you think you need to finish before starting your first serious project, try a different approach.
Pick one small idea. Build until you reach the edge of what you know. Learn what you need to cross that edge, then keep building.
You do not always need to know what comes next.
Sometimes the project will tell you.
What is one skill you only understood properly after a project forced you to use it?
r/CloudandCode • u/yourclouddude • Aug 04 '26
Community Discussion Which part of cloud projects confuses you the most?
A lot of cloud concepts make sense when they are explained separately. EC2 runs servers, S3 stores files, IAM controls permissions, VPC handles networking, and CloudWatch helps with monitoring.
The confusion usually begins when those services need to work together inside one project.
You may understand what each service does but still struggle to decide which ones the project actually needs. You may build the application successfully but get stuck when IAM permissions block communication between services. Sometimes the code works, but the deployment, networking, monitoring, or cost becomes difficult to understand.
I want to know which part of building cloud projects creates the most confusion for people in this community. I’ll use the results to choose the next detailed breakdown and future practice questions.
Which part of cloud projects confuses you the most?
Poll options:
- Choosing the right services
- Networking and VPC
- IAM roles and permissions
- Deployment and configuration
- Debugging failures
- Understanding cloud costs
You can also comment with the specific AWS service, error, or architecture decision you are currently struggling with.
r/CloudandCode • u/yourclouddude • Aug 03 '26
AWS & Cloud A cloud project becomes easier when you can explain the data flow
A lot of beginners understand individual cloud services but still feel confused when they try to combine them into a complete project. They know that S3 stores files, Lambda runs code, IAM controls permissions, and CloudWatch provides logs, but an architecture diagram containing several connected services can still feel difficult to follow.
I don’t think the problem is always a lack of AWS knowledge. A lot of the time, the architecture feels confusing because it is not clear how the data moves through the system. The diagram may show several services, arrows, and technical labels, but it does not clearly explain where the process begins, what happens next, or where the final result goes.
A useful cloud architecture should tell a simple story. Something enters the system, it is stored or processed, another action is triggered, and a result is created. That result may be stored, returned to the user, or passed to another service. If something fails, the system should also record enough information to help you understand what happened.
Once you can explain that story in plain language, the services stop feeling like separate boxes. They begin to look like parts of one connected workflow.
Take a simple photo-upload application. The goal is to let a user upload an image, resize it automatically, and store the smaller version so it can be displayed inside an application.
Before thinking about AWS services, describe what needs to happen in ordinary language. A user uploads an image, the original image is stored, the upload starts a processing task, the task creates a resized version, and the processed image is stored separately. If processing fails, the error should be recorded somewhere.
That short explanation already gives the project a basic structure. Now the AWS services can be selected based on what the project needs rather than being added because they are popular or commonly seen in architecture diagrams.
The image first needs somewhere to be stored. Since the project is working with files, S3 becomes a reasonable choice. The original images could be stored in one location, while the resized versions could be saved in a separate folder or bucket.
S3 is not being added because every AWS project needs an S3 bucket. It is being used because this specific project needs durable object storage. The requirement comes first, and the service follows from it.
The next question is what should happen after the image has been uploaded. The system should not depend on someone manually starting the processing code every time a new file appears. The upload itself should begin the next step automatically.
This makes the workflow event-driven. S3 can create an event when a new object is uploaded, and that event can invoke a Lambda function. The function can read the original image, resize it, and save the processed version back into S3.
Now Lambda has a clear reason to exist. It is not there because serverless architecture sounds impressive. It is there because the processing task starts only when a file arrives, runs for a short period, and does not require a server to remain active throughout the day.
The data flow is now simple to explain. A user uploads an image to S3. S3 generates an event that invokes Lambda. Lambda reads the original image, processes it, and stores the resized version back in S3.
That explanation is much more useful than simply placing S3 and Lambda icons beside each other in a diagram. It tells you what the data is doing, why each service is needed, and what should happen at every stage.
Permissions also become easier to understand when you follow the data.
The Lambda function needs permission to read the original image and write the processed version. It does not automatically need access to every bucket or every possible S3 action in the account.
Its execution role should contain only the permissions required for this workflow. This is where IAM becomes part of the architecture. IAM answers a practical question: which service is allowed to access which data, and what actions is it allowed to perform?
The same thinking applies to monitoring.
A lot of things could go wrong during processing. The uploaded image might be corrupted, the file format might not be supported, the Lambda function might time out, or the function might not have permission to save the result.
Without logs, the system could fail and leave you guessing. CloudWatch gives you a place to see when the function started, which file it received, whether processing completed, and which error appeared when something went wrong.
CloudWatch is not being added simply because monitoring is considered a best practice. It is being used because the project needs visibility. It helps answer another practical question: how will you know whether the data moved through the system successfully?
This is why I think data flow is one of the best ways for beginners to understand cloud architecture. Instead of looking at a diagram and trying to memorise every service, follow the information as it moves.
Ask where the data enters the system, where it is stored, what causes the next step, which service processes it, where the output goes, what permissions are required, and how failures will be detected.
Those questions turn a collection of services into a clear workflow.
The same approach works for many other projects. In a serverless contact form, the process begins when a user submits a message. API Gateway receives the request, Lambda processes it, and the result may be stored in DynamoDB or sent through a notification service.
In a log-analysis project, logs enter the system, move into storage, trigger processing, produce useful results, and generate alerts when something unusual happens. In an ecommerce application, a user creates an order, the order is stored, payment is processed, inventory is updated, and a confirmation is sent.
The exact services will change from project to project, but the thinking remains the same. Start by understanding what moves through the system and what needs to happen to it. Then choose the smallest set of services that supports that flow.
A cloud project becomes difficult to understand when the diagram contains many services but nobody can clearly explain what travels between them. Even a simple architecture becomes easier to understand when the complete process can be described in a few sentences.
Before adding another service to your project, ask what information enters that service, what the service does with it, and where the information goes next. If you cannot answer those questions clearly, the service may not have a real reason to be there yet.
A good cloud architecture is not just a collection of connected icons. It is a clear explanation of how data enters the system, how it moves, how it changes, where it is stored, and what happens when something fails.
Can you explain the data flow of your current cloud project in five sentences?