👋 Hey there, Tech Enthusiasts!
I'm Sarvar, a Cloud Architect who loves turning complex tech problems into simple solutions. I've worked with AWS, Azure, DevOps, Data, Analytics, Generative-AI and Agentic-AI building real systems for real companies. In this article series, I'll share what I've learned in a way that's easy to follow, whether you're experienced or just getting started.
Let's get into it! 🚀
I once woke up to a $14 AWS bill because I forgot to stop an EC2 instance overnight. For a student, that felt like $1400. That one mistake made me afraid to touch anything in AWS for the next three weeks.
I didn't come from a coding background. I didn't have anyone to guide me. I watched videos, read documentation, tried things on the AWS console, and every single time I was terrified of one thing the bill. After that incident, I stopped experimenting freely. I played it safe. And playing it safe is the worst thing you can do when you're trying to learn cloud.
That fear slowed me down by months.
In my first real project, I deployed a Lambda function that wrote to DynamoDB. During development, I never tested what happens when DynamoDB throttles writes because I was too afraid to generate real traffic on AWS. In production, messages started disappearing silently. I spent two days debugging something I could have caught in five minutes if I had a safe local environment to test against.
Today, after years of working as a Cloud Architect across multiple companies and countries, I can tell you this with full confidence the single most important thing that separates a good cloud engineer from a mediocre one is hands-on practice. Not certifications. Not watching 40 hours of video. Hands-on. Breaking things. Fixing things. Understanding why something failed and how to bring it back.
A few months ago I found a tool that solves all of this. It's called Floci an open-source local AWS emulator. You run it in Docker, it gives you 58 AWS services at localhost, and it costs nothing. No AWS account. No credit card. No sign-up. No auth token.
Let me show you how it works.
The Problems You're Probably Facing Right Now
Fear of billing. Every time you try something new creating a VPC, launching an instance, testing Lambda there's this voice saying "what if I forget to delete this?" That fear kills curiosity.
No safe playground. The AWS Free Tier helps, but it has limits. Cross those limits once, and you get charged. For a student or a fresher, even a small unexpected bill feels massive.
Theory without practice. You watched hours of videos about S3 and DynamoDB. You can explain what they are. But can you actually use them? Can you create a bucket from the command line? Can you put data into a table and get it back? If not, you haven't really learned it.
Starting over after every mistake. When something breaks, most beginners delete everything and recreate it. They never learn to troubleshoot. They never learn why it broke. They just run away from the problem and start fresh. I did this for months.
If any of this sounds familiar, keep reading.
Before We Start: What You Need
Two things:
- Docker a tool that runs applications in isolated containers. Think of it as a lightweight virtual machine. Floci runs inside Docker.
- AWS CLI the command-line tool to interact with AWS services (optional, but I strongly recommend it)
That's it. Here's how to install both:
Note: Everything in this tutorial runs 100% offline on your own machine Mac, Windows, or Linux. I'm using an EC2 instance to demonstrate the steps, but that's just my setup. You don't need a cloud server. The exact same commands work on your laptop, completely offline, with no internet required after the initial install. That's the whole point.
Install Docker
Windows / Mac: Download and install Docker Desktop. Open it once installed that's all.
Ubuntu / Debian:
sudo apt-get update && sudo apt-get install -y docker.io docker-compose-v2
sudo systemctl start docker
sudo usermod -aG docker $USER
Amazon Linux / RHEL / Fedora:
sudo dnf install -y docker
sudo systemctl start docker
sudo usermod -aG docker $USER
Install Docker Compose plugin
sudo mkdir -p /usr/local/lib/docker/cli-plugins
sudo curl -SL "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-$(uname -m)" \
-o /usr/local/lib/docker/cli-plugins/docker-compose
sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
After running the Linux commands above, log out and log back in (or run newgrp docker) so the group change takes effect. Otherwise you'll get "permission denied" errors.
Install AWS CLI
Ubuntu / Debian / Amazon Linux:
curl "https://awscli.amazonaws.com/awscli-exe-linux-$(uname -m).zip" -o "awscliv2.zip"
unzip awscliv2.zip && sudo ./aws/install
(If unzip is not found, install it first: sudo apt-get install -y unzip or sudo dnf install -y unzip)
Mac:
curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg"
sudo installer -pkg AWSCLIV2.pkg -target /
Windows: Download and run the installer from:
https://awscli.amazonaws.com/AWSCLIV2.msi
Verify the installation on any platform:
aws --version
Getting Floci Running
Open your terminal, create a new folder, and create the compose file:
mkdir floci-playground && cd floci-playground
Now create a file called docker-compose.yml inside this folder. You can use any text editor VS Code, nano, or even notepad. Paste this content:
services:
floci:
image: floci/floci:latest
ports:
- "4566:4566"
volumes:
- ./data:/app/data
Start it:
docker compose up -d
If you get
docker compose: command not found, try the older syntax:docker-compose up -d. Both work the same way.
Wait a few seconds, then verify it's running:
# Linux / Mac
curl http://localhost:4566/_localstack/health
# Windows (PowerShell)
Invoke-RestMethod http://localhost:4566/_localstack/health
You should see something like this:
{"services":{"s3":"running","sqs":"running","dynamodb":"running","lambda":"running",...},"version":"1.5.25"}
All services showing "running" you're good to go.
Now tell your AWS CLI to talk to Floci instead of real AWS:
# Linux / Mac
export AWS_ENDPOINT_URL=http://localhost:4566
export AWS_DEFAULT_REGION=us-east-1
export AWS_ACCESS_KEY_ID=test
export AWS_SECRET_ACCESS_KEY=test
# Windows (PowerShell)
$env:AWS_ENDPOINT_URL="http://localhost:4566"
$env:AWS_DEFAULT_REGION="us-east-1"
$env:AWS_ACCESS_KEY_ID="test"
$env:AWS_SECRET_ACCESS_KEY="test"
The credentials can be anything. I use test because it's simple. Floci doesn't validate them it just needs non-empty values.
Your First Win: Create an S3 Bucket
S3 is the storage backbone of AWS. Logs go to S3. Backups go to S3. Static websites live on S3. If you understand S3, you already understand 30% of how AWS works.
aws s3 mb s3://my-first-bucket
Output:
make_bucket: my-first-bucket
That's it. You just created a bucket. One command. No console. No waiting.
Now upload a file:
echo "hello from my laptop" | aws s3 cp - s3://my-first-bucket/greeting.txt
Check if it's there:
aws s3 ls s3://my-first-bucket
2026-06-16 11:43:58 21 greeting.txt
Read it back:
aws s3 cp s3://my-first-bucket/greeting.txt -
hello from my laptop
That felt good, right? You just did exactly what production systems do store and retrieve data from S3. The same commands. The same behavior. When you move to real AWS someday, nothing changes except where the data lives.
Challenge: Upload 3 different files to your bucket, then try to delete the bucket without emptying it first. What error do you get? Now figure out how to fix it using only the CLI. This exact scenario comes up in every cloud job.
Create a DynamoDB Table and Store Data
DynamoDB confused me for weeks when I started. But once I actually created a table and put data into it, everything clicked. Let's make that happen for you right now.
Create a table:
aws dynamodb create-table \
--table-name Users \
--attribute-definitions AttributeName=id,AttributeType=S \
--key-schema AttributeName=id,KeyType=HASH \
--billing-mode PAY_PER_REQUEST
Put an item in it:
# Linux / Mac
aws dynamodb put-item \
--table-name Users \
--item '{"id":{"S":"user-001"},"name":{"S":"Sarvar"},"role":{"S":"Cloud Architect"}}'
# Windows (PowerShell) - use double quotes and escape inner quotes
aws dynamodb put-item --table-name Users --item '{\"id\":{\"S\":\"user-001\"},\"name\":{\"S\":\"Sarvar\"},\"role\":{\"S\":\"Cloud Architect\"}}'
A quick note on the JSON format DynamoDB requires you to specify the data type for each value. "S" means String, "N" means Number. It looks verbose at first, but you get used to it quickly.
Get it back:
aws dynamodb get-item \
--table-name Users \
--key '{"id":{"S":"user-001"}}'
{
"Item": {
"id": { "S": "user-001" },
"name": { "S": "Sarvar" },
"role": { "S": "Cloud Architect" }
}
}
You just stored and retrieved structured data from a NoSQL database. That's real cloud development.
Challenge: Put another item with the same id but a different name. Does it overwrite? Does it error? Now put 5 different users and try aws dynamodb scan --table-name Users to get all of them. This is how you learn database behavior by seeing it happen, not reading about it.
Send and Receive Messages with SQS
Almost every production system uses message queues. Order processing, notifications, async workflows queues are everywhere.
Create a queue:
aws sqs create-queue --queue-name orders
Send a message:
aws sqs send-message \
--queue-url http://localhost:4566/000000000000/orders \
--message-body '{"event":"order.placed","item":"cloud-book"}'
(That 000000000000 is the default AWS account ID that Floci uses. In real AWS, it would be your actual 12-digit account number.)
Receive it:
aws sqs receive-message \
--queue-url http://localhost:4566/000000000000/orders
{
"Messages": [
{
"MessageId": "ba4ea32c-cfdf-4c28-b705-8bcbb4d8a0d0",
"Body": "{\"event\":\"order.placed\",\"item\":\"cloud-book\"}"
}
]
}
Your message comes back exactly as you sent it.
Challenge: Receive the same message again. What happens? It disappears for about 30 seconds (this is called "visibility timeout" the time SQS hides a message after someone reads it, giving them time to process it). Wait 30 seconds and try again. It comes back. Now try deleting it after receiving. This is exactly how real applications process queues.
Create a Secret in Secrets Manager
Every application has passwords, API keys, and database credentials. Secrets Manager is where you store them securely.
aws secretsmanager create-secret \
--name my-app/db-password \
--secret-string "super-secret-password-123"
Retrieve it:
aws secretsmanager get-secret-value --secret-id my-app/db-password
{
"Name": "my-app/db-password",
"SecretString": "super-secret-password-123"
}
That's how real applications fetch database credentials at runtime instead of hardcoding them in code. Simple, but incredibly important in production.
Store Configuration in SSM Parameter Store
Parameter Store is where you keep application configuration feature flags, environment URLs, settings that change between dev and production.
aws ssm put-parameter \
--name "/myapp/environment" \
--value "development" \
--type String
aws ssm put-parameter \
--name "/myapp/max-retries" \
--value "3" \
--type String
Get them back:
aws ssm get-parameter --name "/myapp/environment"
aws ssm get-parameters --names "/myapp/environment" "/myapp/max-retries"
This is how every well-architected application manages configuration. No more hardcoding values in your code.
Use It With Python
If you want to go beyond CLI, here's how your application code talks to Floci. Make sure Python 3 is installed, then:
pip install boto3
import boto3
s3 = boto3.client("s3",
endpoint_url="http://localhost:4566",
region_name="us-east-1",
aws_access_key_id="test",
aws_secret_access_key="test")
s3.create_bucket(Bucket="my-python-bucket")
s3.put_object(Bucket="my-python-bucket", Key="hello.txt", Body=b"it works!")
print(s3.get_object(Bucket="my-python-bucket", Key="hello.txt")["Body"].read())
Output: b'it works!'
The only difference between this and production code is one line: endpoint_url. When you deploy to real AWS, remove that line. Everything else stays the same. You're writing production-ready code from day one.
The Way I Wish I Had Learned
Looking back at my journey, here's what I would do differently starting today:
Week 1-2: S3 and IAM. Create buckets, upload files, set permissions, try to access things you shouldn't. Break the permissions. Fix them. Understand what "Access Denied" actually means.
Week 3-4: DynamoDB. Create tables with different key structures. Put data. Query it. Understand the difference between get-item and query and scan.
Week 5-6: SQS, SNS, and Secrets Manager. Build a simple message flow. Store secrets. Retrieve configuration. These are the building blocks of every real application.
Week 7-8: Lambda. Write a simple function. Trigger it. See the logs. Floci runs real Lambda containers not mocks.
Throughout: Break everything. Delete tables while data is in them. Send malformed messages. Call APIs with wrong parameters. Read the error messages carefully. This is the real education.
Tips From Years of Cloud Work
1. Don't just create. Troubleshoot.
The skill that got me promoted from L1 Cloud Support to Cloud Architect wasn't creating infrastructure. It was fixing it when it broke. Break things deliberately on Floci and fix them without starting over.
2. Learn the CLI before the console.
In real jobs, you'll use CLI and infrastructure-as-code. Floci forces this habit because there's no console to click around in.
3. Read error messages. Actually read them.
Most beginners see an error and panic. AWS error messages are surprisingly helpful if you actually read them. Practice generating errors on Floci so you learn to read them calmly.
4. Document what you learn.
I filled four notebooks with cloud concepts. Later, I converted those notes into articles. That habit changed my career. Start writing about what you break and fix even if nobody reads it at first.
5. One concept per day is enough.
You don't need to learn all 200 AWS services. Focus on the core: storage, databases, messaging. One solid hour of hands-on practice beats five hours of video watching.
Common Mistakes Beginners Hit
Before you get stuck, here are the issues I see most often:
- "Command not found: aws" - You haven't installed AWS CLI yet, or you need to restart your terminal after installation.
-
Commands hitting real AWS instead of Floci - You forgot to set
AWS_ENDPOINT_URL. Always check withecho $AWS_ENDPOINT_URLbefore running commands. - "Cannot connect to the Docker daemon" - Docker Desktop isn't running. Open it first.
-
Data disappeared after restart - By default, Floci stores data in memory. Add
FLOCI_STORAGE_MODE=hybridto keep data between restarts:
services:
floci:
image: floci/floci:latest
ports:
- "4566:4566"
environment:
- FLOCI_STORAGE_MODE=hybrid
volumes:
- ./data:/app/data
When You're Ready for Real AWS
Here's the transition path:
- Learn and practice on Floci (no cost, no risk)
- When you feel confident, create an AWS Free Tier account
- Deploy the same commands on real AWS they work identically
- For your application code, just remove the
endpoint_urlline
There is no rewrite. No migration. No new learning curve. The skills you build on Floci transfer directly to real AWS because it's the same API, the same CLI, the same SDK.
Cleaning Up
When you're done for the day:
docker compose down
This stops everything. If you used hybrid storage mode, your data stays in the ./data folder for next time.
Final Thoughts
When I started learning cloud, I was scared of bills, confused by services, and paralyzed by the fear of breaking something expensive. I shipped broken code to production because I couldn't test properly locally. I wasted months playing it safe when I should have been experimenting aggressively.
That was then. Today, you have Floci.
If you're a fresher starting your cloud journey, a student preparing for certifications, or a working professional switching to cloud start here. Build things. Break things. Fix things. Do it a hundred times until the commands feel natural and the errors feel familiar.
The cloud rewards people who practice. Not people who watch.
In my next article, I'll show you how to deploy a complete serverless API Lambda + API Gateway + DynamoDB entirely on Floci, and then move it to real AWS with zero code changes. Follow me so you don't miss it.
Resources:
- Floci GitHub:
Light, fluffy, and always free
No account. No auth token. No feature gates. Justdocker compose upQuick Start · Features · Services · SDKs · Testcontainers · Migration · Docs
What is Floci?
Floci is a free, open-source local AWS emulator for development, testing, and CI.
It gives you AWS-shaped services on your machine without requiring a cloud account, an auth token, or paid feature gates. Point your AWS SDK, CLI, Terraform, CDK, OpenTofu, or test suite at
http://localhost:4566and keep your existing workflows.Floci is named after floccus, the cloud formation that looks like popcorn.
Quick Start
The fastest way to run Floci is with the official CLI
floci start
Export the AWS environment variables:
eval $(floci env)
Use your existing AWS tools normally:
aws s3 mb s3://my-bucket aws dynamodb create-table \ --table-name demo-table \ --attribute-definitions AttributeName=pk,AttributeType=S \ --key-schema AttributeName=pk,KeyType=HASH \ --billing-mode PAY_PER_REQUEST aws
… - Floci Documentation: floci.io/floci/
- Docker Hub: hub.docker.com/r/floci/floci
If this helped you, share it with someone who's starting their cloud journey. Drop a comment if you have questions I'll respond to every one.
Connect with me on LinkedIn for more cloud architecture, DevOps, and career guidance.
📌 Wrapping Up
Thanks for reading! If this was helpful:
- ❤️ Like if it added value
- 💾 Save for later
- 🔄 Share with your team
Follow me for more on: AWS architecture, FinOps, DevOps, and AI Infrastructure.
👉 Visit my website | Connect on LinkedIn | Email: simplynadaf@gmail.com
Happy Learning 🚀


















Top comments (0)