Hands-on AWS tutorials that run entirely on your laptop. No AWS account, no credit card, no credentials, no bill.
Read them here: https://sreekant13.github.io/floci-aws-tutorials/
Each tutorial uses Floci, an MIT-licensed local cloud
emulator that speaks the real AWS wire protocol on localhost:4566. You write
ordinary aws CLI commands and ordinary boto3 or AWS SDK v3 code. The only
difference from real AWS is one endpoint override, and every tutorial points at
exactly where that line is.
Install Floci. Windows:
irm https://floci.io/install.ps1 | iexmacOS and Linux:
curl -fsSL https://floci.io/install.sh | shStart it and point your shell at it:
floci start && eval $(floci env)aws s3 mb s3://hello-floci && aws s3 lsIf that listed your bucket, start at 00-setup.
You need Docker (Floci is a container, and Lambda launches more containers),
AWS CLI v2 (v1 ignores AWS_ENDPOINT_URL), and Python 3.9+ and
Node 18+ for the SDK examples.
| # | Topic | Services | Checks | Time |
|---|---|---|---|---|
| 00 | Setup | - | 11 | 20 min |
| 01 | Object storage | S3 | 17 | 50 min |
| 02 | Key-value data | DynamoDB | 16 | 60 min |
| 03 | Serverless functions | Lambda | 15 | 60 min |
| 04 | Queues and pub/sub | SQS, SNS | 21 | 60 min |
| 05 | A full REST API | API Gateway + Lambda + DynamoDB | 23 | 75 min |
| 06 | Identity and secrets | IAM, STS, Secrets Manager | 23 | 70 min |
| 07 | Orchestration | Step Functions, EventBridge | 24 | 70 min |
| 08 | Infrastructure as code | CloudFormation | 26 | 60 min |
176 checks passing, on Windows locally and on Ubuntu in CI.
Learning AWS the normal way means an account, a card on file, and a standing risk of forgetting to tear something down. That friction is the single biggest barrier to students actually practising cloud work rather than reading about it.
Floci removes it. It starts in about 24ms, idles at roughly 13 MiB, accepts any credentials, and covers 68 AWS services. Lambda, RDS, EC2, ECS and OpenSearch are not emulated at all, since Floci launches real engines in Docker, so those behave very close to production.
The trade is fidelity. Emulation is not the real thing, and pretending otherwise
would make these tutorials actively harmful. So every tutorial ends with a
"How this differs from real AWS" section, populated from
docs/COVERAGE.md, which records what was tested by hand
rather than what the vendor documentation claims.
Every tutorial ships a verify.sh that runs its own documented commands and
fails loudly. Writing those scripts turned up real divergences that are not
documented anywhere, and each one is now written into the relevant tutorial and
asserted in its test, so a future Floci release that changes the behaviour will
break the build rather than quietly make the tutorial wrong.
| Service | What differs | Why it matters |
|---|---|---|
| S3 | Overwriting an object that predates put-bucket-versioning destroys its null version. Real AWS keeps it. |
Silent data loss, with no error raised. The first draft of tutorial 01 walked students straight into it. |
| DynamoDB | Global secondary indexes are updated synchronously. Real AWS indexes are eventually consistent. | Write-then-immediately-query works locally and fails intermittently in production. |
| SQS | Standard queues never reordered or duplicated a message in testing. Real AWS explicitly permits both. | A consumer that is not idempotent passes here and fails in production. An absence of chaos is harder to notice than a missing feature. |
| Lambda | The IAM execution role is not validated. Any ARN is accepted. | On real AWS a role missing log permissions produces a function that runs but writes nothing. That whole failure mode is invisible here. |
| IAM | Policies are stored faithfully and evaluated correctly by the simulator, but never enforced on a real call. An explicit Deny is ignored, as are credentials invented on the spot. |
The largest gap in the series, verified across seven cases. A security control that appears present and does nothing is harder to spot than one that is missing. |
| KMS | encrypt does not encrypt. The ciphertext is a label wrapped around base64 of the plaintext, recoverable with no key. |
Anything put through KMS locally is readable by anyone holding the output. |
| Step Functions | Retry is accepted and never executed. A Task set to retry three times runs exactly once. |
Retry logic that looks correct locally behaves completely differently in production, including timing and the idempotency each step then needs. |
The full list, including what remains unprobed, is in
docs/COVERAGE.md.
docs/TEMPLATE.mdis the structure every tutorial follows. Read it before writing a new one.docs/COVERAGE.mdis the hand-verified support matrix. It is written first, and it decides what gets a tutorial at all.scripts/smoke-test.shprobes candidate services with the operations a tutorial would actually need, and emits the raw matrix.scripts/lib.shholds the assertion helpers everyverify.shuses, plus two Windows workarounds described below.tutorials/NN-*/verify.shruns that tutorial's own commands headless and exits non-zero on failure.scripts/verify-all.shruns every one of them..github/workflows/verify.ymlruns the lot on every push and once a week, so a new Floci release cannot silently break a tutorial.
Run everything locally:
floci start && ./scripts/verify-all.shindex.md landing page for the published site
_config.yml Jekyll config, stock theme, no customisation
_includes/head-custom.html renders mermaid diagrams on GitHub Pages
docs/
TEMPLATE.md the structure every tutorial follows
COVERAGE.md hand-verified support matrix and divergences
scripts/
lib.sh assertion helpers, native_path, msys_safe
smoke-test.sh service probes, emits the raw coverage matrix
verify-all.sh runs every tutorial's verify.sh
tutorials/
00-setup/ README.md, verify.sh
01-s3/ README.md, verify.sh, python/, node/
02-dynamodb/ README.md, verify.sh, python/, node/
03-lambda/ README.md, verify.sh, function/, python/, node/
04-messaging/ README.md, verify.sh, python/, node/
05-serverless-api/ README.md, verify.sh, function/, python/, node/
06-iam/ README.md, verify.sh, python/, node/
07-orchestration/ README.md, verify.sh, function/, python/, node/
08-iac/ README.md, verify.sh, templates/, python/, node/
.github/workflows/verify.yml
03-lambda/function/ holds the handler that actually gets uploaded to Lambda.
It is separate from python/ because it is the deployed artifact rather than a
client script.
Both of these look like Floci bugs and are not. Both are handled by helpers in
scripts/lib.sh, and both cost real time to diagnose the first time.
Paths passed to the AWS CLI. Git Bash hands over a POSIX path such as
/tmp/fn.zip, but the AWS CLI is a native Windows binary and cannot resolve it.
The symptom is Unable to load paramfile. Use native_path(), which wraps
cygpath -w.
Arguments that start with a slash but are not paths. CloudWatch log group
names look like /aws/lambda/my-function. Git Bash rewrites that into
C:/Program Files/Git/aws/lambda/my-function before the CLI sees it, and you
are told the log group does not exist. Use msys_safe(), which sets
MSYS_NO_PATHCONV=1 for a single command. It cannot be set globally, because
that breaks the conversion native_path() depends on.
- Probe the service first:
./scripts/smoke-test.sh <service>. Never document behaviour from vendor documentation. - Record what you found in
docs/COVERAGE.md. - Copy
docs/TEMPLATE.mdtotutorials/NN-name/README.mdand fill it in. - Write
verify.shcovering every claim the README makes. - Run it more than once. Several bugs in this repo only appeared on a second or third consecutive run.
- Confirm
./scripts/verify-all.shpasses from a cleanfloci start.
When a verify script disagrees with the tutorial, work out which one is wrong before fixing either. Twice the answer was the tutorial, and both times that produced the most useful page in the repository.
House style: no em dashes, and no contractions.
Floci needs no credentials and should never be exposed beyond localhost. It
performs no real authorisation, so any request that looks well formed succeeds.
Never point these tutorials at a real AWS endpoint, and never put real
credentials in this repository.
MIT. Use these tutorials, fork them, teach from them, rip out the bits you like. If you republish a chunk, keep the copyright line. That is the whole ask.
You are about to spend a few hours breaking a cloud that cannot bill you. That
is a genuinely rare position to be in, so please misuse it. Delete the thing you
were told not to delete. Feed the function garbage. Run a verify.sh and try to
make it fail. The worst outcome is that you type floci stop and everything you
did evaporates for free.
Nothing here has a credit card attached, so there is no such thing as an expensive mistake. Go and make some cheap ones.
If any of this was useful, a star takes one click and helps the next student find it. If you know somebody who has been putting off learning AWS because of the credit card form, send them this way.
Good luck, and enjoy the low floor.
Built by Sreekant Baheti.
- Portfolio: sreekantbaheti.com
- GitHub: @Sreekant13
Found a typo, a broken command, or a place where Floci does something none of these pages warn you about? Open an issue. Turning up a new divergence is the single most valuable thing you can contribute here, and I will credit you for it on the page you break.
Built as a research assistant project under Dr. Saty Raghavachary, Computer Science Department, University of Southern California.