<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nahuel Nucera</title>
    <description>The latest articles on DEV Community by Nahuel Nucera (@nahuel990).</description>
    <link>https://dev.to/nahuel990</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3842305%2Ffafe7064-02bd-47d1-8838-51df2da5ddd3.png</url>
      <title>DEV Community: Nahuel Nucera</title>
      <link>https://dev.to/nahuel990</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nahuel990"/>
    <language>en</language>
    <item>
      <title>Limp Mode: building a car mechanic that runs offline on a 4B model</title>
      <dc:creator>Nahuel Nucera</dc:creator>
      <pubDate>Sun, 14 Jun 2026 10:50:00 +0000</pubDate>
      <link>https://dev.to/nahuel990/limp-mode-building-a-car-mechanic-that-runs-offline-on-a-4b-model-1iak</link>
      <guid>https://dev.to/nahuel990/limp-mode-building-a-car-mechanic-that-runs-offline-on-a-4b-model-1iak</guid>
      <description>&lt;p&gt;&lt;em&gt;Built for the Build Small Hackathon (Hugging Face and Gradio), Backyard AI track. A&lt;br&gt;
fine-tuned 4B model, a 1.3B vision model, a deterministic safety layer, and a 202-case&lt;br&gt;
benchmark with one number that has to stay at zero.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Seven years ago I hit a bump in a Fiat and the engine died. No damage, no warning light,&lt;br&gt;
just dead, on a road with no signal. The cause turned out to be a crash safety switch&lt;br&gt;
that cuts the engine after an impact. The reset was a hidden button near my knee,&lt;br&gt;
documented on a page of a manual that was not in the car. A tow truck and a mechanic&lt;br&gt;
later, I had the lesson this project is built on: the moment you most need information&lt;br&gt;
about your car is exactly the moment you have no internet.&lt;/p&gt;

&lt;p&gt;Limp Mode is an offline roadside copilot. You photograph the dashboard light, pick it&lt;br&gt;
from a wall of warning lights drawn the way they look on a real dash, describe the noise&lt;br&gt;
in English or Spanish, or enter an OBD code. It answers with a STOP, CAUTION, or DRIVE&lt;br&gt;
verdict, the hidden cause when there is one, and step by step self rescue, because "drive&lt;br&gt;
carefully to a garage" is useless in a dead zone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deterministic skeleton, small-model flesh
&lt;/h2&gt;

&lt;p&gt;The design rule: anything that has to be right is not generated.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;layer&lt;/th&gt;
&lt;th&gt;mechanism&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;OBD code to meaning&lt;/td&gt;
&lt;td&gt;3,369-code database (SAE J2012)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dashboard symbol to meaning&lt;/td&gt;
&lt;td&gt;closed world of 64 telltales; vision proposes, the driver confirms by tapping the glyph&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;severity floor&lt;/td&gt;
&lt;td&gt;hard rules: brakes, oil pressure, overheating, fuel smell, flashing CEL, and flooding can never be downgraded by the model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;hidden causes&lt;/td&gt;
&lt;td&gt;38 verified entries (inertia switches, EV 12V bricks, shift-lock overrides), retrieved and rendered verbatim&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;roadside procedures&lt;/td&gt;
&lt;td&gt;15 step by step guides, rendered verbatim, never paraphrased&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;free-form triage&lt;/td&gt;
&lt;td&gt;Qwen3.5-4B, fine-tuned, strict JSON contract&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The model only does what only a model can do: read a messy human description of a noise&lt;br&gt;
and reason about it. Everything else is data.&lt;/p&gt;

&lt;h2&gt;
  
  
  A benchmark with a zero in it
&lt;/h2&gt;

&lt;p&gt;Before training anything, we built a 202-case suite (52 stop, 96 caution, 54 drive)&lt;br&gt;
across seven categories. Two headline metrics: verdict accuracy, and dangerous-as-safe&lt;br&gt;
(expected STOP, answered DRIVE), which must be exactly zero. Overcaution is also a&lt;br&gt;
failure, so a quarter of the suite is benign cases designed to punish panic.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the measurements caught
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Naive RAG made the model worse.&lt;/strong&gt; Zero-shot, the model alone scored 88.1% accuracy but&lt;br&gt;
surfaced the hidden-cause knowledge only 74% of the time. The first retrieval attempt&lt;br&gt;
pushed knowledge to 100% and crashed accuracy to 59.5%: irrelevant but lexically similar&lt;br&gt;
knowledge-base entries scared the model into overcaution on ordinary cases. The fix was&lt;br&gt;
IDF-weighted retrieval, a prompt contract that treats hits as candidates to ignore unless&lt;br&gt;
they clearly match, and training data that includes noisy retrievals whose correct answer&lt;br&gt;
is to ignore the context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Our own safety floor was the second biggest error source.&lt;/strong&gt; The model is told to&lt;br&gt;
over-flag plausible hazards because the flags feed the floor. The floor treated any flag&lt;br&gt;
as a hard trigger, so "slight pull when braking" got honestly flagged for brakes and&lt;br&gt;
slammed from the correct CAUTION up to STOP. Fourteen of seventeen failures in one run&lt;br&gt;
were the floor, not the model. The fix: hard evidence (text keywords, confirmed symbols,&lt;br&gt;
OBD codes) gets the full floor, while a bare model flag can raise at most to CAUTION. The&lt;br&gt;
full pipeline then reached 90.5% on the seed suite, above the bare model, with knowledge&lt;br&gt;
at 100% and dangerous-as-safe still zero.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The training-data gate found a bug in the safety system.&lt;/strong&gt; Every training example passes&lt;br&gt;
deterministic gates plus decontamination against the eval suite. The floor-consistency&lt;br&gt;
gate started rejecting perfectly good inertia-switch examples, because the floor keyword&lt;br&gt;
list included the bare word "fire", which matches "the engine will not fire". That bug&lt;br&gt;
would have hit real users. A verifier built to check the data ended up debugging the&lt;br&gt;
product.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We red-teamed the human-written layer too.&lt;/strong&gt; The 15 roadside procedures were checked&lt;br&gt;
line by line against AA, RAC, NHTSA, CDC, and manufacturer guidance. Thirteen stood, two&lt;br&gt;
had real problems. Our "drive in a truck's spray shadow" tip for dead wipers was the&lt;br&gt;
opposite of the correct advice (truck spray blinds you, stay back), and our warning&lt;br&gt;
triangle distances matched no actual jurisdiction while several countries now prohibit&lt;br&gt;
placing triangles on motorways at all. Both fixed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Training: Modal, and a week of dependency archaeology
&lt;/h2&gt;

&lt;p&gt;The triage model is a LoRA fine-tune of Qwen3.5-4B (rank 32, completion-only loss, 3&lt;br&gt;
epochs) trained on Modal over 760 quality-gated examples. The honest part of the story is&lt;br&gt;
that the training code worked on the first try and the environment did not, eleven times.&lt;br&gt;
The chain: one trainer library pinned an older version of transformers that did not know&lt;br&gt;
Qwen3.5, so we dropped it; the next library did the same, so we dropped that too; and the&lt;br&gt;
GGUF converter's own requirements file silently downgraded both PyTorch (to a CPU build)&lt;br&gt;
and transformers on every rebuild. The fix was to make the CUDA PyTorch and the correct&lt;br&gt;
transformers the final image layers, with a build-time assertion that fails the build if&lt;br&gt;
either was clobbered.&lt;/p&gt;

&lt;p&gt;One more small-model trap worth writing down: the converter declared a multi-token&lt;br&gt;
prediction head in the GGUF metadata but wrote none of its tensors, so the file would not&lt;br&gt;
load until that metadata was set back to zero.&lt;/p&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;Both rows run through the identical pipeline, so the difference is the fine-tune alone.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;stage&lt;/th&gt;
&lt;th&gt;accuracy&lt;/th&gt;
&lt;th&gt;dangerous-as-safe&lt;/th&gt;
&lt;th&gt;schema valid&lt;/th&gt;
&lt;th&gt;knowledge&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;base Qwen3.5-4B&lt;/td&gt;
&lt;td&gt;83.2%&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;99.5%&lt;/td&gt;
&lt;td&gt;98.9%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fine-tuned&lt;/td&gt;
&lt;td&gt;92.6%&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;td&gt;97.9%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A 9.4 point gain in verdict accuracy, with the dangerous-as-safe count held at zero and&lt;br&gt;
schema validity at 100%. The fine-tune scores 100% on OBD-code and dashboard-symbol cases&lt;br&gt;
and 94.6% on hidden-cause cases; the soft spots it leaves are benign cases (81%, a little&lt;br&gt;
residual overcaution) and Spanish (84%).&lt;/p&gt;

&lt;h2&gt;
  
  
  What it costs
&lt;/h2&gt;

&lt;p&gt;The whole stack, both models quantized, all the knowledge bases, and the front end, runs&lt;br&gt;
on a laptop with the network off, answering in roughly 15 to 20 seconds. The deployed&lt;br&gt;
Space runs the same pipeline on free ZeroGPU hardware.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest limitations
&lt;/h2&gt;

&lt;p&gt;The hidden-cause knowledge base covers 38 entries; coverage is the ceiling, and a miss&lt;br&gt;
means the model reasons unaided. Vision recall on a full dashboard is partial at 1.3B,&lt;br&gt;
which is exactly why the product never trusts it: every detected light is confirmed by the&lt;br&gt;
driver's tap before it feeds the deterministic layer. The procedures are general; a&lt;br&gt;
procedures database for your specific car would be better. That is the roadmap: the&lt;br&gt;
owner's manual, finally useful, finally offline.&lt;/p&gt;

&lt;p&gt;Try it: &lt;a href="https://huggingface.co/spaces/build-small-hackathon/limp-mode" rel="noopener noreferrer"&gt;https://huggingface.co/spaces/build-small-hackathon/limp-mode&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>gradio</category>
      <category>opensource</category>
    </item>
    <item>
      <title>We gave Kiro a brain for AWS, locally, for free</title>
      <dc:creator>Nahuel Nucera</dc:creator>
      <pubDate>Thu, 28 May 2026 08:21:03 +0000</pubDate>
      <link>https://dev.to/nahuel990/we-gave-kiro-a-brain-for-aws-locally-for-free-5haj</link>
      <guid>https://dev.to/nahuel990/we-gave-kiro-a-brain-for-aws-locally-for-free-5haj</guid>
      <description>&lt;p&gt;We built MiniStack (a local AWS emulator) when LocalStack moved its core services behind a paywall. It runs on a single port at &lt;code&gt;http://localhost:4566&lt;/code&gt;, emulates around 60 AWS services, and costs nothing. Day to day, we use it for testing AWS code and for prototyping new services without spending a cent on a real account.&lt;/p&gt;

&lt;p&gt;The piece that was missing was the editor side of the loop. We work in Kiro. Kiro is a strong agentic IDE. But every new AWS workflow inside the editor started with the same overhead: telling Kiro where to point the SDK clients, reminding it of the testing patterns we use, walking it through which service does what for the case at hand. Repetitive context we'd already written down somewhere else.&lt;/p&gt;

&lt;p&gt;So we pulled all of it into a Kiro Power. The Power ships steering files for the services we use most, a testing workflow file, and a manifest that activates the moment you mention MiniStack or AWS in chat. Kiro picks it up automatically, no manual prompting.&lt;/p&gt;

&lt;p&gt;That's what this post is about. It's called &lt;strong&gt;MiniStack × Kiro&lt;/strong&gt;, it's open source, and it's about removing the repetitive context-loading step from every AWS session.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changes once you install it
&lt;/h2&gt;

&lt;p&gt;Kiro picks up specific behaviors the moment you mention AWS or MiniStack in chat:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It configures your boto3, AWS CLI, Terraform, and CDK setups against &lt;code&gt;localhost:4566&lt;/code&gt; with the right test credentials, without asking you for them.&lt;/li&gt;
&lt;li&gt;It writes service-specific code that actually runs against MiniStack. Not pseudocode. Real S3 calls. Real DynamoDB conditional updates. Real Step Functions ASL.&lt;/li&gt;
&lt;li&gt;It walks you through services you don't know yet. There are steering files for S3, SQS, SNS, DynamoDB, Lambda, IAM, Step Functions, EventBridge, API Gateway, Cognito, and CloudWatch. Each one is a hands-on guide written for the local-first workflow.&lt;/li&gt;
&lt;li&gt;It knows the reset endpoint, so when you ask it to run a test scenario from scratch, it resets the right state instead of polluting it.&lt;/li&gt;
&lt;li&gt;It handles multi-tenancy properly. MiniStack scopes resources by your access-key-as-account-ID. The Power knows this and reuses it when you want isolated environments per developer or per CI lane.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The steering files were extracted from real workflows we run every week, not synthesised.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing it
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7kg69pgg2zx53d1o5weq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7kg69pgg2zx53d1o5weq.png" alt="Ministack x Kiro" width="800" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Two paths, both take under a minute.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From the GitHub repo:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open Kiro, click the Powers icon in the sidebar.&lt;/li&gt;
&lt;li&gt;Add Custom Power, then GitHub Repository.&lt;/li&gt;
&lt;li&gt;Paste &lt;code&gt;https://github.com/ministackorg/ministack-power&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Click Add.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;From a local folder, if you cloned it:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open Kiro, click the Powers icon.&lt;/li&gt;
&lt;li&gt;Add Custom Power, then Local Directory.&lt;/li&gt;
&lt;li&gt;Paste the absolute path to the folder you cloned.&lt;/li&gt;
&lt;li&gt;Click Add.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it. The Power activates automatically when you talk to Kiro about AWS or MiniStack.&lt;/p&gt;

&lt;p&gt;You'll also want MiniStack itself running. One line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;ministack &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; ministack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It boots in around two seconds and uses around 30 MB of RAM at idle. Health check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:4566/_ministack/health
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What it looks like in practice
&lt;/h2&gt;

&lt;p&gt;A few examples from real sessions, since "Kiro plus a Power" sounds abstract until you see it doing work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;S3 presigned URLs.&lt;/strong&gt;&lt;br&gt;
A Python script that uploads a file via presigned PUT, downloads it via presigned GET, then verifies the round-trip. The Power pulls in the S3 steering file, the script gets generated pointed at &lt;code&gt;localhost:4566&lt;/code&gt; with the right SigV4 settings, runs, and you see the output. No clarifying questions about endpoint configuration. No "let me check the AWS docs first."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DynamoDB conditional writes.&lt;/strong&gt;&lt;br&gt;
Three test cases against the local DynamoDB exercising &lt;code&gt;ConditionExpression&lt;/code&gt; plus &lt;code&gt;ReturnValuesOnConditionCheckFailure=ALL_OLD&lt;/code&gt;. The case where the condition fails and the API returns the existing item in the error body is the one most emulators get wrong; MiniStack handles it correctly, and the Power knows to test for it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step Functions ASL.&lt;/strong&gt;&lt;br&gt;
A state machine with a &lt;code&gt;Map&lt;/code&gt; iterator over 100 items, executed locally, with the per-iteration results inspected via &lt;code&gt;GetExecutionHistory&lt;/code&gt;. The whole loop happens on the laptop. No AWS bill. No clean-up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Serverless REST API.&lt;/strong&gt;&lt;br&gt;
API Gateway plus Lambda plus DynamoDB, CRUD endpoints, end-to-end. The Power has a dedicated steering file for this pattern. Kiro scaffolds the project, writes the Lambda handlers, wires the API Gateway integrations, creates the DynamoDB table, and runs the end-to-end test against MiniStack. The whole thing takes minutes instead of the hour you'd burn on real AWS worrying about IAM roles and accidentally provisioning something you forgot to tear down.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters more than "Kiro got smarter"
&lt;/h2&gt;

&lt;p&gt;What this combination removes from the loop is the interesting part.&lt;/p&gt;

&lt;p&gt;When you're learning AWS, the cost of an experiment is friction. Spinning up a real account, creating a sandbox, watching for forgotten resources, dealing with permissions. Even if the dollar amount is small, the cognitive load isn't. A lot of people give up on learning new AWS services not because the services are hard, but because the friction of trying things is high.&lt;/p&gt;

&lt;p&gt;When you're testing existing AWS code, the cost is reliability. If your CI pipeline depends on LocalStack's free tier (no longer free) or on shared sandbox accounts, you're at the mercy of something outside your control. MiniStack runs on the laptop. The Power makes it talk fluently with Kiro. The whole loop becomes a closed system you own.&lt;/p&gt;

&lt;p&gt;That's the value. It's not "AI plus AWS." It's the removal of friction from both sides.&lt;/p&gt;

&lt;h2&gt;
  
  
  Some things to know
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;MiniStack is MIT licensed. The Power is MIT licensed.&lt;/strong&gt; There's no upsell, no paid tier, no telemetry. It runs entirely on your machine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can use the Power without MiniStack.&lt;/strong&gt; Kiro will still pick up the steering content and apply it. But the loop only closes when both are running.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Power doesn't ship steering for every AWS service yet.&lt;/strong&gt; It covers the 10 services we use daily plus the serverless-REST-API pattern. Pull requests welcome at &lt;code&gt;github.com/ministackorg/ministack-power&lt;/code&gt;. If you want a service added, opening an issue is enough.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;State persistence is opt-in.&lt;/strong&gt; Set &lt;code&gt;PERSIST_STATE=1&lt;/code&gt; when you start MiniStack and it survives restarts. The Power knows about this and will mention it when you're building anything that needs durability across runs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Two Power variants on the backlog:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A Terraform-first variant.&lt;/strong&gt; Same steering, but every example is &lt;code&gt;terraform apply&lt;/code&gt; against the local endpoint instead of boto3 or CLI. Useful for infra teams who think in HCL.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A CDK-first variant.&lt;/strong&gt; Same idea, but using &lt;code&gt;cdk synth&lt;/code&gt; and &lt;code&gt;cdk deploy --endpoint-url&lt;/code&gt;. Useful for application teams who already use CDK.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If either sounds useful, open an issue on the repo so we know to prioritise it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;ministack &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; ministack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then install the Power in Kiro using &lt;code&gt;https://github.com/ministackorg/ministack-power&lt;/code&gt;. Talk to Kiro about anything AWS. You'll feel the difference within a few prompts.&lt;/p&gt;

&lt;p&gt;If something breaks, file an issue at &lt;code&gt;github.com/ministackorg/ministack-power/issues&lt;/code&gt;. If something works well, tell people. That's how this stuff spreads.&lt;/p&gt;

&lt;p&gt;Links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MiniStack: &lt;code&gt;github.com/ministackorg/ministack&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The Power: &lt;code&gt;github.com/ministackorg/ministack-power&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;PyPI: &lt;code&gt;pypi.org/project/ministack/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Docker Hub: &lt;code&gt;hub.docker.com/r/ministackorg/ministack&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kiro</category>
      <category>aws</category>
      <category>opensource</category>
      <category>devops</category>
    </item>
    <item>
      <title>MiniStack now emulates MWAA. Develop and test Airflow DAGs locally, skip the $353/month</title>
      <dc:creator>Nahuel Nucera</dc:creator>
      <pubDate>Sun, 17 May 2026 10:57:31 +0000</pubDate>
      <link>https://dev.to/nahuel990/ministack-now-emulates-mwaa-develop-and-test-airflow-dags-locally-skip-the-353month-2ehp</link>
      <guid>https://dev.to/nahuel990/ministack-now-emulates-mwaa-develop-and-test-airflow-dags-locally-skip-the-353month-2ehp</guid>
      <description>&lt;p&gt;MWAA costs $353/month. That's $0.49/hour, 24/7, just for the environment to exist. Whether you're actively developing DAGs, running tests in CI, or doing nothing at all; you pay.&lt;/p&gt;

&lt;p&gt;MiniStack now emulates MWAA. You can develop and validate Airflow DAGs locally. DAG structure, task routing, API calls on a single Docker container. No AWS environment needed until you deploy to production.&lt;/p&gt;

&lt;p&gt;If you had a dedicated MWAA environment for development and testing, that's $353/month you no longer need.&lt;/p&gt;

&lt;p&gt;And MWAA is just one piece. Here's what a full integration test suite actually costs on AWS.&lt;/p&gt;

&lt;h2&gt;
  
  
  The scenario
&lt;/h2&gt;

&lt;p&gt;A typical integration test suite that validates cloud infrastructure:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fprlovykp6rd8o4vlc3tb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fprlovykp6rd8o4vlc3tb.png" alt="Services" width="800" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test Type&lt;/th&gt;
&lt;th&gt;What It Validates&lt;/th&gt;
&lt;th&gt;AWS Services Used&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Table schema checks&lt;/td&gt;
&lt;td&gt;Partition keys, GSIs, TTL, billing, PITR&lt;/td&gt;
&lt;td&gt;DynamoDB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Parameter verification&lt;/td&gt;
&lt;td&gt;Config values, paths, naming&lt;/td&gt;
&lt;td&gt;SSM Parameter Store&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Object storage ops&lt;/td&gt;
&lt;td&gt;Upload, list, download, cleanup&lt;/td&gt;
&lt;td&gt;S3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ETL job execution&lt;/td&gt;
&lt;td&gt;Data transformation pipeline&lt;/td&gt;
&lt;td&gt;Glue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Query validation&lt;/td&gt;
&lt;td&gt;Output correctness&lt;/td&gt;
&lt;td&gt;Athena&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Workflow orchestration&lt;/td&gt;
&lt;td&gt;DAG structure, task routing&lt;/td&gt;
&lt;td&gt;MWAA (Airflow)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Serverless functions&lt;/td&gt;
&lt;td&gt;Event processing, API handlers&lt;/td&gt;
&lt;td&gt;Lambda&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Message queues&lt;/td&gt;
&lt;td&gt;Pub/sub, FIFO ordering&lt;/td&gt;
&lt;td&gt;SQS&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Per test run&lt;/strong&gt;: ~50 DynamoDB operations, ~10 S3 operations, 9 Glue jobs (10 workers, ~4 min each), 20 Athena queries, 4 MWAA API calls.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost per test run by region
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1z1ajevuqa39gmus5dbw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1z1ajevuqa39gmus5dbw.png" alt="Cost per run" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;th&gt;Dominance&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Glue&lt;/strong&gt; (9 jobs x 10 workers x 4 min)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$2.64&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;99.9%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DynamoDB (50 reads + 25 writes)&lt;/td&gt;
&lt;td&gt;$0.0001&lt;/td&gt;
&lt;td&gt;~0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;S3 (~25 requests, 1MB data)&lt;/td&gt;
&lt;td&gt;$0.0001&lt;/td&gt;
&lt;td&gt;~0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Athena (20 queries x 10MB min)&lt;/td&gt;
&lt;td&gt;$0.001&lt;/td&gt;
&lt;td&gt;~0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSM (3 GetParameter calls)&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MWAA (API calls only, env already running)&lt;/td&gt;
&lt;td&gt;$0.00&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Per-run cost is identical across all regions: ~$2.64&lt;/strong&gt; (Glue pricing is uniform)&lt;/p&gt;

&lt;p&gt;The only regional variation is in DynamoDB and S3, which together account for less than $0.001 per run — negligible.&lt;/p&gt;

&lt;h2&gt;
  
  
  AWS pricing by region
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Services with uniform global pricing
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Unit&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Glue ETL&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;DPU-hour (G.1X)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.44&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Athena&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Per TB scanned (10MB min)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$5.00&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MWAA mw1.small&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Per hour&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.49&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MWAA mw1.medium&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Per hour&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.74&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Lambda&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Per 1M requests&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.20&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Lambda&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Per GB-second&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.0000166667&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQS Standard&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Per 1M requests&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.40&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SSM Standard&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;API calls + storage&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Free&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  DynamoDB on-demand (per 1M request units)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Region&lt;/th&gt;
&lt;th&gt;Writes (WRU)&lt;/th&gt;
&lt;th&gt;Reads (RRU)&lt;/th&gt;
&lt;th&gt;vs US baseline&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;us-east-1 (N. Virginia)&lt;/td&gt;
&lt;td&gt;$0.625&lt;/td&gt;
&lt;td&gt;$0.125&lt;/td&gt;
&lt;td&gt;baseline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;us-west-2 (Oregon)&lt;/td&gt;
&lt;td&gt;$0.625&lt;/td&gt;
&lt;td&gt;$0.125&lt;/td&gt;
&lt;td&gt;same&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;eu-west-1 (Ireland)&lt;/td&gt;
&lt;td&gt;$0.705&lt;/td&gt;
&lt;td&gt;$0.142&lt;/td&gt;
&lt;td&gt;+13%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;eu-central-1 (Frankfurt)&lt;/td&gt;
&lt;td&gt;$0.763&lt;/td&gt;
&lt;td&gt;$0.153&lt;/td&gt;
&lt;td&gt;+22%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ap-southeast-1 (Singapore)&lt;/td&gt;
&lt;td&gt;$0.710&lt;/td&gt;
&lt;td&gt;$0.143&lt;/td&gt;
&lt;td&gt;+14%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ap-northeast-1 (Tokyo)&lt;/td&gt;
&lt;td&gt;$0.715&lt;/td&gt;
&lt;td&gt;$0.143&lt;/td&gt;
&lt;td&gt;+14%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  S3 Standard
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Region&lt;/th&gt;
&lt;th&gt;Storage $/GB/mo&lt;/th&gt;
&lt;th&gt;PUT per 1K&lt;/th&gt;
&lt;th&gt;GET per 1K&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;us-east-1&lt;/td&gt;
&lt;td&gt;$0.023&lt;/td&gt;
&lt;td&gt;$0.005&lt;/td&gt;
&lt;td&gt;$0.0004&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;us-west-2&lt;/td&gt;
&lt;td&gt;$0.023&lt;/td&gt;
&lt;td&gt;$0.005&lt;/td&gt;
&lt;td&gt;$0.0004&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;eu-west-1&lt;/td&gt;
&lt;td&gt;$0.023&lt;/td&gt;
&lt;td&gt;$0.005&lt;/td&gt;
&lt;td&gt;$0.0004&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;eu-central-1&lt;/td&gt;
&lt;td&gt;$0.0245&lt;/td&gt;
&lt;td&gt;$0.0054&lt;/td&gt;
&lt;td&gt;$0.00043&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ap-southeast-1&lt;/td&gt;
&lt;td&gt;$0.025&lt;/td&gt;
&lt;td&gt;$0.005&lt;/td&gt;
&lt;td&gt;$0.0004&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ap-northeast-1&lt;/td&gt;
&lt;td&gt;$0.025&lt;/td&gt;
&lt;td&gt;$0.0047&lt;/td&gt;
&lt;td&gt;$0.00037&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Monthly cost: AWS vs MiniStack
&lt;/h2&gt;

&lt;h3&gt;
  
  
  AWS monthly cost by test frequency
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Frequency&lt;/th&gt;
&lt;th&gt;Runs/month&lt;/th&gt;
&lt;th&gt;Test Cost&lt;/th&gt;
&lt;th&gt;MWAA env (24/7)&lt;/th&gt;
&lt;th&gt;Total&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2x/week&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;$24&lt;/td&gt;
&lt;td&gt;$353&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$377&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1x/day&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;$79&lt;/td&gt;
&lt;td&gt;$353&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$432&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3x/day&lt;/td&gt;
&lt;td&gt;90&lt;/td&gt;
&lt;td&gt;$238&lt;/td&gt;
&lt;td&gt;$353&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$591&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5x/day&lt;/td&gt;
&lt;td&gt;150&lt;/td&gt;
&lt;td&gt;$396&lt;/td&gt;
&lt;td&gt;$353&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$749&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10x/day&lt;/td&gt;
&lt;td&gt;300&lt;/td&gt;
&lt;td&gt;$792&lt;/td&gt;
&lt;td&gt;$353&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$1,145&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Note: MWAA is typically shared infrastructure (dev + test + orchestration), not test-only. Attributing 20% to testing: ~$71/month.&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Frequency&lt;/th&gt;
&lt;th&gt;Test Cost&lt;/th&gt;
&lt;th&gt;+ MWAA (20%)&lt;/th&gt;
&lt;th&gt;Monthly Total&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2x/week&lt;/td&gt;
&lt;td&gt;$24&lt;/td&gt;
&lt;td&gt;$71&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$95&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1x/day&lt;/td&gt;
&lt;td&gt;$79&lt;/td&gt;
&lt;td&gt;$71&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$150&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3x/day&lt;/td&gt;
&lt;td&gt;$238&lt;/td&gt;
&lt;td&gt;$71&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$309&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5x/day&lt;/td&gt;
&lt;td&gt;$396&lt;/td&gt;
&lt;td&gt;$71&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$467&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10x/day&lt;/td&gt;
&lt;td&gt;$792&lt;/td&gt;
&lt;td&gt;$71&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$863&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  MiniStack monthly cost
&lt;/h3&gt;

&lt;p&gt;MiniStack runs on a CI runner. No AWS charges.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Docker container startup&lt;/td&gt;
&lt;td&gt;~2 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test execution (41 infra tests)&lt;/td&gt;
&lt;td&gt;~1 second&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CI runner time (~2 min total)&lt;/td&gt;
&lt;td&gt;$0.016 per run&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Frequency&lt;/th&gt;
&lt;th&gt;Runs/month&lt;/th&gt;
&lt;th&gt;MiniStack Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2x/week&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.14&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1x/day&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.48&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3x/day&lt;/td&gt;
&lt;td&gt;90&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$1.44&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5x/day&lt;/td&gt;
&lt;td&gt;150&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$2.40&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10x/day&lt;/td&gt;
&lt;td&gt;300&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$4.80&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Based on standard CI runner at $0.008/minute, 2 minutes per run.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Savings summary
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnny19cv5mqe7rrvqptvo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnny19cv5mqe7rrvqptvo.png" alt="Savings with Ministack" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Monthly savings (AWS → MiniStack)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Frequency&lt;/th&gt;
&lt;th&gt;AWS/month&lt;/th&gt;
&lt;th&gt;MiniStack/month&lt;/th&gt;
&lt;th&gt;Saving&lt;/th&gt;
&lt;th&gt;%&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2x/week&lt;/td&gt;
&lt;td&gt;$95&lt;/td&gt;
&lt;td&gt;$0.14&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$95&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;99.9%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1x/day&lt;/td&gt;
&lt;td&gt;$150&lt;/td&gt;
&lt;td&gt;$0.48&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$150&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;99.7%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3x/day&lt;/td&gt;
&lt;td&gt;$309&lt;/td&gt;
&lt;td&gt;$1.44&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$308&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;99.5%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5x/day&lt;/td&gt;
&lt;td&gt;$467&lt;/td&gt;
&lt;td&gt;$2.40&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$465&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;99.5%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10x/day&lt;/td&gt;
&lt;td&gt;$863&lt;/td&gt;
&lt;td&gt;$4.80&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$858&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;99.4%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Annual savings
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Frequency&lt;/th&gt;
&lt;th&gt;AWS/year&lt;/th&gt;
&lt;th&gt;MiniStack/year&lt;/th&gt;
&lt;th&gt;Annual Saving&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2x/week&lt;/td&gt;
&lt;td&gt;$1,140&lt;/td&gt;
&lt;td&gt;$2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$1,138&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1x/day&lt;/td&gt;
&lt;td&gt;$1,800&lt;/td&gt;
&lt;td&gt;$6&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$1,794&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3x/day&lt;/td&gt;
&lt;td&gt;$3,708&lt;/td&gt;
&lt;td&gt;$17&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$3,691&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5x/day&lt;/td&gt;
&lt;td&gt;$5,604&lt;/td&gt;
&lt;td&gt;$29&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$5,575&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10x/day&lt;/td&gt;
&lt;td&gt;$10,356&lt;/td&gt;
&lt;td&gt;$58&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$10,298&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Volume / performance testing (occasional)
&lt;/h2&gt;

&lt;p&gt;These run against real AWS (not practical on a local emulator due to cluster scale):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test&lt;/th&gt;
&lt;th&gt;Rows&lt;/th&gt;
&lt;th&gt;Glue Duration&lt;/th&gt;
&lt;th&gt;Glue Cost&lt;/th&gt;
&lt;th&gt;S3&lt;/th&gt;
&lt;th&gt;Athena&lt;/th&gt;
&lt;th&gt;Total&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;5M rows&lt;/td&gt;
&lt;td&gt;5,100,000&lt;/td&gt;
&lt;td&gt;~30 min&lt;/td&gt;
&lt;td&gt;$2.20&lt;/td&gt;
&lt;td&gt;$0.001&lt;/td&gt;
&lt;td&gt;$0.02&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$2.22&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15M rows&lt;/td&gt;
&lt;td&gt;15,000,000&lt;/td&gt;
&lt;td&gt;~60 min&lt;/td&gt;
&lt;td&gt;$4.40&lt;/td&gt;
&lt;td&gt;$0.003&lt;/td&gt;
&lt;td&gt;$0.05&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$4.45&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;30M rows&lt;/td&gt;
&lt;td&gt;30,000,000&lt;/td&gt;
&lt;td&gt;~120 min&lt;/td&gt;
&lt;td&gt;$8.80&lt;/td&gt;
&lt;td&gt;$0.007&lt;/td&gt;
&lt;td&gt;$0.11&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$8.92&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Running all three once per month: &lt;strong&gt;~$16/month&lt;/strong&gt; additional.&lt;/p&gt;

&lt;h2&gt;
  
  
  What runs where
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2011b2ed5sd8k13c9yc9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2011b2ed5sd8k13c9yc9.png" alt="What runs where" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test Category&lt;/th&gt;
&lt;th&gt;MiniStack&lt;/th&gt;
&lt;th&gt;Real AWS&lt;/th&gt;
&lt;th&gt;Cost Driver&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DynamoDB schema + CRUD&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Optional&lt;/td&gt;
&lt;td&gt;DynamoDB: free-tier negligible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSM parameter checks&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Optional&lt;/td&gt;
&lt;td&gt;SSM: free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;S3 upload/download&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Optional&lt;/td&gt;
&lt;td&gt;S3: pennies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Glue ETL pipeline&lt;/td&gt;
&lt;td&gt;No*&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Glue: $2.64/run&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Athena query validation&lt;/td&gt;
&lt;td&gt;No*&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Athena: pennies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MWAA DAG validation&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Optional&lt;/td&gt;
&lt;td&gt;MWAA: $353/mo fixed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lambda function tests&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Optional&lt;/td&gt;
&lt;td&gt;Lambda: free tier covers it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SQS message flow&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Optional&lt;/td&gt;
&lt;td&gt;SQS: free tier covers it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Volume/perf tests&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Glue at scale&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;MiniStack supports Glue catalog operations and Athena (via DuckDB), but running full PySpark ETL jobs locally requires additional setup (local Spark + Iceberg).&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick start
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Start MiniStack
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# docker-compose.yml&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ministack&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ministackorg/ministack:latest&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;4566:4566"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Provision infrastructure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;

&lt;span class="n"&gt;endpoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:4566&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;ddb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dynamodb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;endpoint_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;aws_access_key_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;aws_secret_access_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;region_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us-east-1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;ddb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;TableName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my-table&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;KeySchema&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AttributeName&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pk&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;KeyType&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HASH&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="n"&gt;AttributeDefinitions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AttributeName&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pk&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AttributeType&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;S&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="n"&gt;BillingMode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PAY_PER_REQUEST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Point tests at MiniStack
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# One config change — everything else stays the same
&lt;/span&gt;&lt;span class="n"&gt;endpoint_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ENDPOINT_URL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# None for real AWS
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;make_client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;kwargs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;endpoint_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;endpoint_url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;endpoint_url&lt;/span&gt;
        &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;aws_access_key_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;aws_secret_access_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;region_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us-east-1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Real AWS&lt;/span&gt;
pytest tests/

&lt;span class="c"&gt;# MiniStack&lt;/span&gt;
&lt;span class="nv"&gt;ENDPOINT_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4566 pytest tests/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Run in CI
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# GitHub Actions example&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;integration-tests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;ministack&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ministackorg/ministack:latest&lt;/span&gt;
        &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;4566:4566&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pip install boto3 pytest&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python scripts/provision.py&lt;/span&gt;  &lt;span class="c1"&gt;# Create tables, params, buckets&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ENDPOINT_URL=http://localhost:4566 pytest tests/ -v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No AWS credentials. No IAM roles. No VPN. Every push, every PR.&lt;/p&gt;

&lt;h2&gt;
  
  
  Free tier reminder
&lt;/h2&gt;

&lt;p&gt;If running against real AWS at low frequency, free tier covers most services:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Free Tier&lt;/th&gt;
&lt;th&gt;Covers test suite?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DynamoDB&lt;/td&gt;
&lt;td&gt;25 GB + 25 RRU/WRU provisioned (always free)&lt;/td&gt;
&lt;td&gt;On-demand mode: not covered, but cost is &amp;lt; $0.01/run&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;S3&lt;/td&gt;
&lt;td&gt;5 GB + 20K GET + 2K PUT (12 months)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lambda&lt;/td&gt;
&lt;td&gt;1M requests + 400K GB-s (always free)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SQS&lt;/td&gt;
&lt;td&gt;1M requests (always free)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSM Standard&lt;/td&gt;
&lt;td&gt;10K parameters + API calls (always free)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Glue&lt;/td&gt;
&lt;td&gt;No free tier&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Not covered&lt;/strong&gt; — this is the cost&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Athena&lt;/td&gt;
&lt;td&gt;No free tier (but $0.001/run)&lt;/td&gt;
&lt;td&gt;Negligible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MWAA&lt;/td&gt;
&lt;td&gt;No free tier&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$353/month minimum&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Bottom line&lt;/strong&gt;: Glue and MWAA are the only services that cost real money for testing. MiniStack eliminates the need for both in CI.&lt;/p&gt;




&lt;h2&gt;
  
  
  Services supported by MiniStack
&lt;/h2&gt;

&lt;p&gt;55+ AWS services including: S3, DynamoDB, Lambda, SQS, SNS, SSM, Glue, Athena, MWAA, Step Functions, ECS, RDS, ElastiCache, Kinesis, EventBridge, Cognito, KMS, IAM, STS, Secrets Manager, CloudWatch, CloudFormation, API Gateway, Route53, EKS, ECR, and more.&lt;/p&gt;

&lt;p&gt;Full list: &lt;a href="https://github.com/ministackorg/ministack" rel="noopener noreferrer"&gt;github.com/ministackorg/ministack&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some tools paywall their services. MiniStack is MIT licensed. Free forever.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ministackorg/ministack" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; · &lt;a href="https://hub.docker.com/r/ministackorg/ministack" rel="noopener noreferrer"&gt;Docker Hub&lt;/a&gt; · &lt;a href="https://ministack.org" rel="noopener noreferrer"&gt;ministack.org&lt;/a&gt; · &lt;a href="https://www.linkedin.com/company/ministackorg" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;All pricing verified against AWS published rates for 2025/2026. MiniStack is MIT-licensed open-source software. CI runner costs based on GitHub Actions standard runners at $0.008/minute.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>airflow</category>
      <category>devops</category>
      <category>opensource</category>
    </item>
    <item>
      <title>What landed in MiniStack between 1.2.0 and 1.3.30</title>
      <dc:creator>Nahuel Nucera</dc:creator>
      <pubDate>Thu, 07 May 2026 16:10:04 +0000</pubDate>
      <link>https://dev.to/nahuel990/what-landed-in-ministack-between-120-and-1330-3c74</link>
      <guid>https://dev.to/nahuel990/what-landed-in-ministack-between-120-and-1330-3c74</guid>
      <description>&lt;h1&gt;
  
  
  MiniStack 1.3.30 is out — here's what shipped recently
&lt;/h1&gt;

&lt;p&gt;MiniStack is a free, MIT-licensed local AWS emulator. Single binary, 55+ services, runs on your laptop or in CI in under a second. No login, no token, no per-seat fee.&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/ministackorg/ministack" rel="noopener noreferrer"&gt;https://github.com/ministackorg/ministack&lt;/a&gt;&lt;br&gt;
Docs: &lt;a href="https://ministack.org/docs/" rel="noopener noreferrer"&gt;https://ministack.org/docs/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Highlights since 1.3.20
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step Functions &lt;code&gt;aws-sdk:s3&lt;/code&gt; integrations.&lt;/strong&gt; &lt;code&gt;arn:aws:states:::aws-sdk:s3:listObjectsV2&lt;/code&gt; and 11 other S3 operations now work as native Step Functions SDK integrations: &lt;code&gt;ListBuckets&lt;/code&gt;, &lt;code&gt;CreateBucket&lt;/code&gt;, &lt;code&gt;DeleteBucket&lt;/code&gt;, &lt;code&gt;HeadBucket&lt;/code&gt;, &lt;code&gt;GetBucketVersioning&lt;/code&gt;, &lt;code&gt;ListObjectsV2&lt;/code&gt;, &lt;code&gt;ListObjects&lt;/code&gt;, &lt;code&gt;HeadObject&lt;/code&gt;, &lt;code&gt;CopyObject&lt;/code&gt;, &lt;code&gt;DeleteObject&lt;/code&gt;, &lt;code&gt;GetObjectTagging&lt;/code&gt;, &lt;code&gt;PutObjectTagging&lt;/code&gt;. REST-JSON output also moved to PascalCase to match the rest of the dispatcher, so &lt;code&gt;ResultSelector: $.Records&lt;/code&gt; resolves cleanly on &lt;code&gt;aws-sdk:rdsdata:executeStatement&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EC2 &lt;code&gt;DescribeVpcEndpointServices&lt;/code&gt;.&lt;/strong&gt; Returns the standard catalog of 2 Gateway services (&lt;code&gt;s3&lt;/code&gt;, &lt;code&gt;dynamodb&lt;/code&gt;) and 17 Interface PrivateLink services with region-templated DNS names. &lt;code&gt;ServiceNames&lt;/code&gt;, &lt;code&gt;service-name&lt;/code&gt;, and &lt;code&gt;service-type&lt;/code&gt; filters supported.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DynamoDB legacy parameters.&lt;/strong&gt; &lt;code&gt;Expected&lt;/code&gt;, &lt;code&gt;KeyConditions&lt;/code&gt;, &lt;code&gt;ScanFilter&lt;/code&gt;, &lt;code&gt;QueryFilter&lt;/code&gt;, and &lt;code&gt;AttributeUpdates&lt;/code&gt; all work now. The .NET AWS SDK was silently dropping non-key fields on every &lt;code&gt;UpdateItem&lt;/code&gt; because it speaks the legacy attribute API under the hood. Fixed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ECS Task Metadata V4.&lt;/strong&gt; Every container started by &lt;code&gt;RunTask&lt;/code&gt; now gets &lt;code&gt;ECS_CONTAINER_METADATA_URI_V4&lt;/code&gt; injected. The gateway serves &lt;code&gt;/v4/&amp;lt;token&amp;gt;&lt;/code&gt;, &lt;code&gt;/v4/&amp;lt;token&amp;gt;/task&lt;/code&gt;, and the &lt;code&gt;/stats&lt;/code&gt; endpoints. &lt;code&gt;RunTask&lt;/code&gt; also translates &lt;code&gt;privileged&lt;/code&gt;, &lt;code&gt;linuxParameters.capabilities.add&lt;/code&gt;, &lt;code&gt;pidMode: host&lt;/code&gt;, and &lt;code&gt;volumes&lt;/code&gt; + &lt;code&gt;mountPoints&lt;/code&gt; into Docker bind mounts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AWS CloudTrail.&lt;/strong&gt; New service. In-memory audit log, opt in via &lt;code&gt;CLOUDTRAIL_RECORDING=1&lt;/code&gt;. Per-account ring buffer with &lt;code&gt;LookupEvents&lt;/code&gt; covering all eight &lt;code&gt;LookupAttributes&lt;/code&gt;. Full control plane: &lt;code&gt;CreateTrail&lt;/code&gt;, &lt;code&gt;DeleteTrail&lt;/code&gt;, &lt;code&gt;Get/DescribeTrails&lt;/code&gt;, &lt;code&gt;StartLogging&lt;/code&gt;/&lt;code&gt;StopLogging&lt;/code&gt; with real &lt;code&gt;IsLogging&lt;/code&gt; state, &lt;code&gt;Put/GetEventSelectors&lt;/code&gt;, tag ops.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AWS Resource Groups.&lt;/strong&gt; New service, 19 of 23 spec operations. Group CRUD, resource queries, configuration, membership, tagging, account settings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CloudFormation &lt;code&gt;AWS::CloudFront::KeyValueStore&lt;/code&gt;.&lt;/strong&gt; Create / Update / Delete with &lt;code&gt;Arn&lt;/code&gt;, &lt;code&gt;Id&lt;/code&gt;, &lt;code&gt;Status&lt;/code&gt; exposed via &lt;code&gt;Fn::GetAtt&lt;/code&gt;. The CFN engine now routes previously-provisioned resources through a per-type &lt;code&gt;update&lt;/code&gt; handler when one is defined.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OpenSearch non-VPC domains.&lt;/strong&gt; &lt;code&gt;VPCOptions&lt;/code&gt; is now omitted on non-VPC domains instead of returning an empty object, which was causing the Terraform AWS provider to misclassify them as VPC-backed and fail with &lt;code&gt;OpenSearch Domain in VPC expected to have null Endpoint value&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;API Gateway v1 fixes.&lt;/strong&gt; &lt;code&gt;GetUsagePlanKey&lt;/code&gt; handler added (Terraform's &lt;code&gt;aws_api_gateway_usage_plan_key&lt;/code&gt; apply was aborting without it). &lt;code&gt;HTTP_PROXY&lt;/code&gt; integrations now do path-parameter substitution from &lt;code&gt;integration.request.path.X = method.request.path.X&lt;/code&gt; mappings and forward the query string. &lt;code&gt;UpdateModel&lt;/code&gt; handler added.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step Functions REST-JSON casing.&lt;/strong&gt; Successful REST-JSON integrations like &lt;code&gt;aws-sdk:rdsdata:executeStatement&lt;/code&gt; now expose output keys in PascalCase (&lt;code&gt;Records&lt;/code&gt;, &lt;code&gt;NumberOfRecordsUpdated&lt;/code&gt;) instead of raw camelCase, matching query and REST-XML dispatchers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SQS &lt;code&gt;ReceiveMessage&lt;/code&gt; honours &lt;code&gt;MessageSystemAttributeNames&lt;/code&gt;.&lt;/strong&gt; Only the deprecated &lt;code&gt;AttributeNames&lt;/code&gt; was being read, so AWS SDK v2 (Java, Kotlin) consumers were getting empty &lt;code&gt;Attributes&lt;/code&gt; and broken &lt;code&gt;ApproximateReceiveCount&lt;/code&gt;-based redelivery detection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SFN &lt;code&gt;aws-sdk:ec2&lt;/code&gt; security group compatibility.&lt;/strong&gt; &lt;code&gt;CreateSecurityGroup&lt;/code&gt; now maps SDK &lt;code&gt;Description&lt;/code&gt; to wire &lt;code&gt;GroupDescription&lt;/code&gt;, &lt;code&gt;DescribeSecurityGroups&lt;/code&gt; sends EC2-shaped filters (&lt;code&gt;Filter.1.Value.1&lt;/code&gt; instead of &lt;code&gt;member.N&lt;/code&gt;), and the XML adapter returns &lt;code&gt;SecurityGroups&lt;/code&gt; rather than raw &lt;code&gt;SecurityGroupInfo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CFN &lt;code&gt;AWS::SNS::Subscription&lt;/code&gt; honours &lt;code&gt;RawMessageDelivery&lt;/code&gt;.&lt;/strong&gt; The provisioner was silently defaulting to &lt;code&gt;false&lt;/code&gt; even when templates set &lt;code&gt;true&lt;/code&gt;, so consumers got SNS-wrapped envelopes instead of raw payloads.&lt;/p&gt;
&lt;h2&gt;
  
  
  Wire-format parity (what makes the project worth using)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;All JSON timestamps are int epoch seconds. Java SDK v2 rejects floats. STS &lt;code&gt;Credentials.Expiration&lt;/code&gt;, EventBridge &lt;code&gt;Time&lt;/code&gt;, EKS &lt;code&gt;createdAt&lt;/code&gt;, CloudTrail &lt;code&gt;EventTime&lt;/code&gt;, Backup, Firehose — all converted.&lt;/li&gt;
&lt;li&gt;KMS &lt;code&gt;Verify&lt;/code&gt; raises &lt;code&gt;KMSInvalidSignatureException&lt;/code&gt; on bad signatures instead of returning &lt;code&gt;SignatureValid: false&lt;/code&gt; with HTTP 200.&lt;/li&gt;
&lt;li&gt;KMS crypto operations return the full key ARN as &lt;code&gt;KeyId&lt;/code&gt;, not the bare UUID.&lt;/li&gt;
&lt;li&gt;DynamoDB &lt;code&gt;ConditionalCheckFailedException&lt;/code&gt; populates &lt;code&gt;Item&lt;/code&gt; when &lt;code&gt;ReturnValuesOnConditionCheckFailure="ALL_OLD"&lt;/code&gt; is set, on &lt;code&gt;Put&lt;/code&gt;/&lt;code&gt;Update&lt;/code&gt;/&lt;code&gt;Delete&lt;/code&gt;/&lt;code&gt;TransactWriteItems&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;EC2 VPCs include &lt;code&gt;cidrBlockAssociationSet&lt;/code&gt; (Terraform AWS provider v6 crashes without it).&lt;/li&gt;
&lt;li&gt;SQS FIFO &lt;code&gt;DeduplicationScope: messageGroup&lt;/code&gt; actually scopes per message group.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 4566:4566 ministackorg/ministack:1.3.30
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Or pip:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;ministack
ministack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Point AWS CLI / boto3 / Terraform at &lt;code&gt;http://localhost:4566&lt;/code&gt; with any non-empty access key.&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/ministackorg/ministack" rel="noopener noreferrer"&gt;https://github.com/ministackorg/ministack&lt;/a&gt;&lt;br&gt;
Docs: &lt;a href="https://ministack.org/docs/" rel="noopener noreferrer"&gt;https://ministack.org/docs/&lt;/a&gt;&lt;br&gt;
LinkedIn: &lt;a href="https://www.linkedin.com/company/ministackorg/" rel="noopener noreferrer"&gt;https://www.linkedin.com/company/ministackorg/&lt;/a&gt;&lt;br&gt;
Reddit: &lt;a href="https://www.reddit.com/r/ministack/" rel="noopener noreferrer"&gt;https://www.reddit.com/r/ministack/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If something is missing or wrong, open an issue.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>aws</category>
      <category>kubernetes</category>
      <category>devops</category>
    </item>
    <item>
      <title>What landed in MiniStack between 1.2.0 and 1.3.30</title>
      <dc:creator>Nahuel Nucera</dc:creator>
      <pubDate>Thu, 07 May 2026 07:27:11 +0000</pubDate>
      <link>https://dev.to/nahuel990/what-landed-in-ministack-between-120-and-1330-3k20</link>
      <guid>https://dev.to/nahuel990/what-landed-in-ministack-between-120-and-1330-3k20</guid>
      <description>&lt;p&gt;If you read the 1.2.0 post, that is where this picks up. About four weeks have gone by and over fifty patch releases. This is a tour of what actually shipped, focused on the parts you can use today.&lt;/p&gt;

&lt;p&gt;If you have not seen MiniStack before: it is a single-binary local AWS emulator. One process, 46 services, MIT licensed, runs on your laptop or in CI in under a second. Think LocalStack without the paywall and without the JVM.&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/ministackorg/ministack" rel="noopener noreferrer"&gt;https://github.com/ministackorg/ministack&lt;/a&gt;&lt;br&gt;
Docs: &lt;a href="https://ministack.org/docs/" rel="noopener noreferrer"&gt;https://ministack.org/docs/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  New services
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;EKS with real k3s&lt;/strong&gt; (1.2.20). &lt;code&gt;CreateCluster&lt;/code&gt; spawns a 75 MB k3s container that gives you a real Kubernetes API. &lt;code&gt;kubectl&lt;/code&gt; and Helm work against it. CloudFormation provisioners for &lt;code&gt;AWS::EKS::Cluster&lt;/code&gt; and &lt;code&gt;AWS::EKS::Nodegroup&lt;/code&gt; are wired in. If Docker is unavailable the cluster still goes ACTIVE with a stub endpoint so the API contract holds in CI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Transfer Family&lt;/strong&gt; (1.2.17). 10 operations covering server CRUD, user CRUD, SSH key rotation, and LOGICAL home directory mappings to S3. Contributed by @mjdavidson.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EventBridge Scheduler&lt;/strong&gt; (1.2.19). The full &lt;code&gt;scheduler&lt;/code&gt; API: schedule groups, cascading deletes, name and state filters, plus &lt;code&gt;at()&lt;/code&gt;, &lt;code&gt;cron()&lt;/code&gt;, and &lt;code&gt;rate()&lt;/code&gt; expressions. CFN &lt;code&gt;AWS::Scheduler::Schedule&lt;/code&gt; and &lt;code&gt;AWS::Scheduler::ScheduleGroup&lt;/code&gt; provisioners included. EventBridge &lt;code&gt;cron()&lt;/code&gt; rules also fire automatically now (1.3.25), with a zero-dependency parser that covers the full six-field syntax including &lt;code&gt;L&lt;/code&gt;, &lt;code&gt;LW&lt;/code&gt;, &lt;code&gt;&amp;lt;n&amp;gt;W&lt;/code&gt;, &lt;code&gt;&amp;lt;n&amp;gt;#&amp;lt;k&amp;gt;&lt;/code&gt;. Contributed by &lt;a class="mentioned-user" href="https://dev.to/hiddengearz"&gt;@hiddengearz&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resource Groups Tagging API&lt;/strong&gt; (1.3.2). &lt;code&gt;GetResources&lt;/code&gt;, &lt;code&gt;GetTagKeys&lt;/code&gt;, &lt;code&gt;GetTagValues&lt;/code&gt; across 15 services (S3, Lambda, SQS, SNS, DynamoDB, EventBridge, KMS, ECR, ECS, Glue, Cognito, AppSync, Scheduler, CloudFront, EFS). Contributed by @AdigaAkhil.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resource Groups&lt;/strong&gt; (1.3.27). 19 of 23 spec operations: group CRUD, resource queries, configuration, membership, tagging, account settings. Requested by @staranto.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AWS CloudTrail&lt;/strong&gt; (1.3.27). In-memory audit log with control plane and &lt;code&gt;LookupEvents&lt;/code&gt;. Per-account ring buffer, opt-in via &lt;code&gt;CLOUDTRAIL_RECORDING=1&lt;/code&gt;. Contributed by @AdigaAkhil.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AppSync Events API&lt;/strong&gt; (1.3.25). Event API management, channel namespaces, API keys, HTTP publish, and realtime WebSocket on the &lt;code&gt;aws-appsync-event-ws&lt;/code&gt; subprotocol. Contributed by @marcin-nowak-scl.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CloudFront KeyValueStore&lt;/strong&gt; (1.3.25, 1.3.26). Both planes: management plane for &lt;code&gt;Create&lt;/code&gt;/&lt;code&gt;Describe&lt;/code&gt;/&lt;code&gt;List&lt;/code&gt;/&lt;code&gt;Update&lt;/code&gt;/&lt;code&gt;Delete&lt;/code&gt; with ETag concurrency, and a separate &lt;code&gt;cloudfront-keyvaluestore&lt;/code&gt; data plane for &lt;code&gt;GetKey&lt;/code&gt;/&lt;code&gt;PutKey&lt;/code&gt;/&lt;code&gt;DeleteKey&lt;/code&gt;/&lt;code&gt;UpdateKeys&lt;/code&gt;. CFN &lt;code&gt;AWS::CloudFront::KeyValueStore&lt;/code&gt; provisioner included. Contributed by &lt;a class="mentioned-user" href="https://dev.to/davireisvieira"&gt;@davireisvieira&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Lambda
&lt;/h2&gt;

&lt;p&gt;A big stretch of work. Highlights:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RIE-based Docker executor&lt;/strong&gt; (1.2.20). &lt;code&gt;LAMBDA_EXECUTOR=docker&lt;/code&gt; now uses official AWS Lambda Runtime Interface Emulator images for every runtime. Containers stay warm between invocations. Originally contributed by @fzonneveld.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Runtime coverage&lt;/strong&gt; (1.2.21 and after). The full image map today: &lt;code&gt;python3.8&lt;/code&gt; through &lt;code&gt;python3.14&lt;/code&gt;, &lt;code&gt;nodejs14.x&lt;/code&gt; through &lt;code&gt;nodejs24.x&lt;/code&gt;, &lt;code&gt;java8.al2&lt;/code&gt;, &lt;code&gt;java11&lt;/code&gt;, &lt;code&gt;java17&lt;/code&gt;, &lt;code&gt;java21&lt;/code&gt;, &lt;code&gt;java25&lt;/code&gt;, &lt;code&gt;dotnet6&lt;/code&gt;, &lt;code&gt;dotnet8&lt;/code&gt;, &lt;code&gt;dotnet10&lt;/code&gt;, &lt;code&gt;ruby3.2&lt;/code&gt;, &lt;code&gt;ruby3.3&lt;/code&gt;, &lt;code&gt;ruby3.4&lt;/code&gt;, plus &lt;code&gt;provided&lt;/code&gt;, &lt;code&gt;provided.al2&lt;/code&gt;, &lt;code&gt;provided.al2023&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lambda to CloudWatch Logs&lt;/strong&gt; (1.3.3). Every invocation now writes &lt;code&gt;START&lt;/code&gt;, handler output, &lt;code&gt;END&lt;/code&gt;, and &lt;code&gt;REPORT&lt;/code&gt; lines to &lt;code&gt;/aws/lambda/{FunctionName}&lt;/code&gt; on a per-invocation stream. Metric filters, subscription filters, and alarm chains that needed real Lambda logs work locally now. Applies to every executor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Async retry and DLQ routing&lt;/strong&gt; (1.3.3). &lt;code&gt;Invoke(InvocationType=Event)&lt;/code&gt; and S3-notification fan-out retry up to &lt;code&gt;MaximumRetryAttempts&lt;/code&gt; and route the final failure to the configured DLQ or &lt;code&gt;OnFailure&lt;/code&gt; destination (SQS, SNS, or another Lambda) with the AWS-shaped envelope.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Docker-in-Docker&lt;/strong&gt; (1.2.21). Running MiniStack inside Docker with &lt;code&gt;LAMBDA_EXECUTOR=docker&lt;/code&gt; works. Code is copied via &lt;code&gt;docker cp&lt;/code&gt; instead of bind-mounted, and Lambda containers are reached via container IP. Reported by @HackJack-101.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Filter criteria during polling&lt;/strong&gt; (1.3.3). SQS, Kinesis, and DynamoDB Streams pollers evaluate each record against &lt;code&gt;FilterCriteria.Filters&lt;/code&gt; and drop non-matching records before invoking. Equality lists, &lt;code&gt;prefix&lt;/code&gt;, &lt;code&gt;suffix&lt;/code&gt;, &lt;code&gt;anything-but&lt;/code&gt;, &lt;code&gt;exists&lt;/code&gt;, and &lt;code&gt;numeric&lt;/code&gt; content filters are all supported.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step Functions aws-sdk:* integrations
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Resource: arn:aws:states:::aws-sdk:&amp;lt;service&amp;gt;:&amp;lt;op&amp;gt;&lt;/code&gt; works against the following services in 1.3.30. The list is the actual contents of the dispatch table in &lt;code&gt;ministack/services/stepfunctions.py&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Query protocol&lt;/strong&gt;: &lt;code&gt;ec2&lt;/code&gt;, &lt;code&gt;sqs&lt;/code&gt;, &lt;code&gt;sns&lt;/code&gt;, &lt;code&gt;rds&lt;/code&gt;, &lt;code&gt;elasticache&lt;/code&gt;, &lt;code&gt;iam&lt;/code&gt;, &lt;code&gt;sts&lt;/code&gt;, &lt;code&gt;cloudwatch&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JSON protocol&lt;/strong&gt;: &lt;code&gt;dynamodb&lt;/code&gt;, &lt;code&gt;secretsmanager&lt;/code&gt;, &lt;code&gt;states&lt;/code&gt; (Step Functions calling itself), &lt;code&gt;logs&lt;/code&gt; (CloudWatch Logs), &lt;code&gt;ssm&lt;/code&gt;, &lt;code&gt;eventbridge&lt;/code&gt;, &lt;code&gt;kinesis&lt;/code&gt;, &lt;code&gt;glue&lt;/code&gt;, &lt;code&gt;athena&lt;/code&gt;, &lt;code&gt;ecs&lt;/code&gt;, &lt;code&gt;ecr&lt;/code&gt;, &lt;code&gt;kms&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;REST-JSON protocol&lt;/strong&gt;: &lt;code&gt;rdsdata&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;REST-XML protocol&lt;/strong&gt;: &lt;code&gt;s3&lt;/code&gt; (12 ops added in 1.3.29: &lt;code&gt;ListBuckets&lt;/code&gt;, &lt;code&gt;CreateBucket&lt;/code&gt;, &lt;code&gt;DeleteBucket&lt;/code&gt;, &lt;code&gt;HeadBucket&lt;/code&gt;, &lt;code&gt;GetBucketVersioning&lt;/code&gt;, &lt;code&gt;ListObjectsV2&lt;/code&gt;, &lt;code&gt;ListObjects&lt;/code&gt;, &lt;code&gt;HeadObject&lt;/code&gt;, &lt;code&gt;CopyObject&lt;/code&gt;, &lt;code&gt;DeleteObject&lt;/code&gt;, &lt;code&gt;GetObjectTagging&lt;/code&gt;, &lt;code&gt;PutObjectTagging&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lambda&lt;/strong&gt;: dispatched directly to the local Lambda invoker&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;REST-JSON output now uses PascalCase to match the query and REST-XML dispatchers (1.3.30, contributed by @jayjanssen), so &lt;code&gt;ResultSelector: $.Records&lt;/code&gt; works on &lt;code&gt;aws-sdk:rdsdata:executeStatement&lt;/code&gt; results.&lt;/p&gt;
&lt;h2&gt;
  
  
  CloudFormation
&lt;/h2&gt;

&lt;p&gt;New provisioners since 1.2.0:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;AWS::Events::EventBus&lt;/code&gt; (1.2.21, contributed by @AdigaAkhil)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AWS::Pipes::Pipe&lt;/code&gt; (1.3.2, contributed by @davidtme), with &lt;code&gt;FilterPolicy&lt;/code&gt; and &lt;code&gt;FilterPolicyScope&lt;/code&gt; on &lt;code&gt;AWS::SNS::Subscription&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AWS::Scheduler::Schedule&lt;/code&gt;, &lt;code&gt;AWS::Scheduler::ScheduleGroup&lt;/code&gt; (1.2.19)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AWS::CodeBuild::Project&lt;/code&gt; (1.2.19, contributed by @AdigaAkhil)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AWS::EKS::Cluster&lt;/code&gt;, &lt;code&gt;AWS::EKS::Nodegroup&lt;/code&gt; (1.2.20)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AWS::CloudFront::KeyValueStore&lt;/code&gt; (1.3.26), with the engine now routing previously-provisioned resources through a per-type &lt;code&gt;update&lt;/code&gt; handler when one is defined&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Infrastructure
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Hypercorn ASGI with HTTP/2 h2c&lt;/strong&gt; (1.3.1). Replaces uvicorn. AWS Java SDK v2 and the Kinesis Client Library work out of the box. Idle RAM dropped from about 21 MB to about 7 MB. Contributed by @AdigaAkhil.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lazy service imports&lt;/strong&gt; (1.2.19). Service modules load on first request. Idle RAM dropped from 59 MB to 21 MB before the hypercorn cut, startup time from 1.2 s to 0.5 s. Services you never call cost zero memory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Per-PR preview Docker images&lt;/strong&gt; (1.3.2). Every PR (including forks) publishes &lt;code&gt;ministackorg/ministack-preview-build:pr-N-&amp;lt;shortsha&amp;gt;&lt;/code&gt;. Reviewers can &lt;code&gt;docker pull&lt;/code&gt; the exact build before merge. Contributed by &lt;a class="mentioned-user" href="https://dev.to/jgrumboe"&gt;@jgrumboe&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Multi-tenancy correctness
&lt;/h2&gt;

&lt;p&gt;1.3.3 closed eight cross-account leaks where services stored per-tenant data in plain &lt;code&gt;dict&lt;/code&gt; or &lt;code&gt;list&lt;/code&gt; (CloudWatch metrics and alarm history, ElastiCache events, EventBridge buses, Athena workgroups and data catalogs, SES sent emails, API Gateway v1 stages, deployments, authorizers, and tags). All of them now route through &lt;code&gt;AccountScopedDict&lt;/code&gt;, with isolation tests in &lt;code&gt;tests/test_multitenancy.py&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Wire-format fixes worth knowing
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;All timestamps in JSON responses are int epoch seconds. The Java SDK v2 rejects floats. STS &lt;code&gt;Credentials.Expiration&lt;/code&gt;, EventBridge &lt;code&gt;Time&lt;/code&gt;, EKS &lt;code&gt;createdAt&lt;/code&gt;, Backup, Firehose, CloudTrail timestamps were converted across 1.3.x.&lt;/li&gt;
&lt;li&gt;KMS &lt;code&gt;Verify&lt;/code&gt; raises &lt;code&gt;KMSInvalidSignatureException&lt;/code&gt; on bad signatures instead of returning &lt;code&gt;SignatureValid: false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;KMS crypto operations return the full key ARN as &lt;code&gt;KeyId&lt;/code&gt;, not the bare UUID.&lt;/li&gt;
&lt;li&gt;DynamoDB &lt;code&gt;ConditionalCheckFailedException&lt;/code&gt; populates &lt;code&gt;Item&lt;/code&gt; when &lt;code&gt;ReturnValuesOnConditionCheckFailure="ALL_OLD"&lt;/code&gt; is set, on &lt;code&gt;Put&lt;/code&gt;/&lt;code&gt;Update&lt;/code&gt;/&lt;code&gt;Delete&lt;/code&gt;/&lt;code&gt;TransactWriteItems&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;EC2 VPCs include &lt;code&gt;cidrBlockAssociationSet&lt;/code&gt; (Terraform AWS provider v6 crashes without it).&lt;/li&gt;
&lt;li&gt;SQS FIFO &lt;code&gt;DeduplicationScope: messageGroup&lt;/code&gt; actually scopes per message group.&lt;/li&gt;
&lt;li&gt;SQS &lt;code&gt;ReceiveMessage&lt;/code&gt; honours &lt;code&gt;MessageSystemAttributeNames&lt;/code&gt;. AWS SDK v2 was the only thing reading it (1.3.29, contributed by @joaomena).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Get it
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 4566:4566 ministackorg/ministack:1.3.30
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Or pip:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;ministack
ministack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub: &lt;a href="https://github.com/ministackorg/ministack" rel="noopener noreferrer"&gt;https://github.com/ministackorg/ministack&lt;/a&gt;&lt;br&gt;
Docs: &lt;a href="https://ministack.org/docs/" rel="noopener noreferrer"&gt;https://ministack.org/docs/&lt;/a&gt;&lt;br&gt;
LinkedIn: &lt;a href="https://www.linkedin.com/company/ministackorg/" rel="noopener noreferrer"&gt;https://www.linkedin.com/company/ministackorg/&lt;/a&gt;&lt;br&gt;
Reddit: &lt;a href="https://www.reddit.com/r/ministack/" rel="noopener noreferrer"&gt;https://www.reddit.com/r/ministack/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If something you need is missing or wrong, open an issue. Most of what is listed above started as one.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>aws</category>
      <category>kubernetes</category>
      <category>devops</category>
    </item>
    <item>
      <title>MiniStack Now Emulates Amazon EKS — Free, Open-Source AWS Emulator v1.2.20</title>
      <dc:creator>Nahuel Nucera</dc:creator>
      <pubDate>Fri, 17 Apr 2026 19:02:33 +0000</pubDate>
      <link>https://dev.to/nahuel990/ministack-now-emulates-amazon-eks-free-open-source-aws-emulator-v1220-2900</link>
      <guid>https://dev.to/nahuel990/ministack-now-emulates-amazon-eks-free-open-source-aws-emulator-v1220-2900</guid>
      <description>&lt;h2&gt;
  
  
  EKS Joins the Free AWS Emulator
&lt;/h2&gt;

&lt;p&gt;MiniStack v1.2.20 adds &lt;strong&gt;Amazon EKS&lt;/strong&gt; to its list of emulated AWS services. Create clusters, manage node groups, and hit the EKS API surface — all locally, all free.&lt;/p&gt;

&lt;p&gt;If you haven't seen MiniStack before: it's a free, MIT-licensed AWS emulator. 40+ services on a single Docker container, single port (4566). No account, no API key, no telemetry. Drop-in compatible with the AWS CLI, Terraform, CDK, and every AWS SDK.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 4566:4566 nahuelnucera/ministack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  EKS Emulation in Action
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4566 eks create-cluster &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; my-cluster &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--role-arn&lt;/span&gt; arn:aws:iam::123456789012:role/eks-role &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--resources-vpc-config&lt;/span&gt; &lt;span class="nv"&gt;subnetIds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;subnet-1,securityGroupIds&lt;span class="o"&gt;=&lt;/span&gt;sg-1

aws &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4566 eks describe-cluster &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; my-cluster

aws &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4566 eks create-nodegroup &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cluster-name&lt;/span&gt; my-cluster &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--nodegroup-name&lt;/span&gt; my-nodes &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--node-role&lt;/span&gt; arn:aws:iam::123456789012:role/node-role &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--subnets&lt;/span&gt; subnet-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Terraform and CDK work without changes — just point your provider endpoint to &lt;code&gt;localhost:4566&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;EKS is one of those services that's painful to test against real AWS. Clusters take 10-15 minutes to provision, cost money even when idle, and are overkill when all you need is to validate your IaC or integration logic.&lt;/p&gt;

&lt;p&gt;With MiniStack, your Terraform plans, CDK deploys, and SDK integration tests hit a local EKS API instantly. No cluster spin-up time, no AWS bill.&lt;/p&gt;

&lt;h2&gt;
  
  
  What MiniStack Emulates (40+ Services)
&lt;/h2&gt;

&lt;p&gt;Not just EKS. The full list keeps growing:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Core (in-memory):&lt;/strong&gt;&lt;br&gt;
S3, SQS, SNS, DynamoDB, Lambda, IAM, STS, Secrets Manager, CloudWatch Logs, SSM Parameter Store, EventBridge, Kinesis, CloudWatch Metrics, SES, Step Functions, Cognito, API Gateway, CloudFormation, ACM, Route 53, Cloud Map&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Infrastructure (real Docker containers):&lt;/strong&gt;&lt;br&gt;
RDS (real Postgres/MySQL), ElastiCache (real Redis), ECS (real Docker containers), Athena (real SQL via DuckDB), Glue&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compute &amp;amp; Container:&lt;/strong&gt;&lt;br&gt;
EC2, EKS, ECR, Auto Scaling, ELBv2&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data &amp;amp; Analytics:&lt;/strong&gt;&lt;br&gt;
Firehose, Redshift, S3 Files&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Other:&lt;/strong&gt;&lt;br&gt;
AppConfig, CodeBuild, Scheduler, Resource Groups Tagging API&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Compares
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;LocalStack Free&lt;/th&gt;
&lt;th&gt;LocalStack Pro&lt;/th&gt;
&lt;th&gt;MiniStack&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;EKS&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅ Paid&lt;/td&gt;
&lt;td&gt;✅ Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Core services&lt;/td&gt;
&lt;td&gt;Now paid&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅ Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RDS/ElastiCache/ECS&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅ Real containers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Startup&lt;/td&gt;
&lt;td&gt;~30s&lt;/td&gt;
&lt;td&gt;~30s&lt;/td&gt;
&lt;td&gt;~2s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RAM at idle&lt;/td&gt;
&lt;td&gt;~500MB&lt;/td&gt;
&lt;td&gt;~500MB&lt;/td&gt;
&lt;td&gt;~21MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Image size&lt;/td&gt;
&lt;td&gt;~1GB&lt;/td&gt;
&lt;td&gt;~1GB&lt;/td&gt;
&lt;td&gt;~270MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;License&lt;/td&gt;
&lt;td&gt;BSL&lt;/td&gt;
&lt;td&gt;Proprietary&lt;/td&gt;
&lt;td&gt;MIT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Price&lt;/td&gt;
&lt;td&gt;Paid&lt;/td&gt;
&lt;td&gt;$35+/mo&lt;/td&gt;
&lt;td&gt;Free forever&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 4566:4566 nahuelnucera/ministack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No account. No API key. No telemetry.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/ministackorg/ministack" rel="noopener noreferrer"&gt;github.com/ministackorg/ministack&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Docker Hub: &lt;a href="https://hub.docker.com/r/nahuelnucera/ministack" rel="noopener noreferrer"&gt;nahuelnucera/ministack&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Website: &lt;a href="https://ministack.org" rel="noopener noreferrer"&gt;ministack.org&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;MIT licensed. PRs welcome.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>docker</category>
      <category>java</category>
      <category>aws</category>
    </item>
    <item>
      <title>MiniStack: Free Local AWS Emulator + Testcontainers Module + AWS CLI Built In</title>
      <dc:creator>Nahuel Nucera</dc:creator>
      <pubDate>Tue, 14 Apr 2026 10:44:56 +0000</pubDate>
      <link>https://dev.to/nahuel990/ministack-free-local-aws-emulator-testcontainers-module-aws-cli-built-in-ne8</link>
      <guid>https://dev.to/nahuel990/ministack-free-local-aws-emulator-testcontainers-module-aws-cli-built-in-ne8</guid>
      <description>&lt;p&gt;4 releases in a weekend: Testcontainers Java module, AWS CLI bundled, Step Functions intrinsics, RDS Data stubs. Free, open-source, MIT licensed.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;We shipped 4 releases this weekend (v1.2.6 through v1.2.9):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;org.ministack:testcontainers-ministack:0.1.0&lt;/code&gt;&lt;/strong&gt; on Maven Central&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;62 bug fixes&lt;/strong&gt; found by running 2,490 tests across all 41 services&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS CLI bundled&lt;/strong&gt; in the Docker image — init scripts just work&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Step Functions intrinsics&lt;/strong&gt; — 7 new functions (ArrayContains, MathAdd, UUID, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RDS Data API stubs&lt;/strong&gt; — test database provisioning without Docker-in-Docker&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  What is MiniStack?
&lt;/h2&gt;

&lt;p&gt;MiniStack is a free, MIT-licensed local AWS emulator. One Docker image, one port (4566), 41 services. It started as a response to LocalStack moving core services behind a paid plan.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Image size:&lt;/strong&gt; 269MB (was 242MB before CLI)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Startup time:&lt;/strong&gt; &amp;lt;2 seconds&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Services:&lt;/strong&gt; S3, DynamoDB, SQS, SNS, Lambda, Step Functions, CloudFormation, EC2, ECS, and 32 more&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker:&lt;/strong&gt; &lt;code&gt;ministackorg/ministack&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/ministackorg/ministack" rel="noopener noreferrer"&gt;ministackorg/ministack&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No license keys. No pro tiers. Just run it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 4566:4566 ministackorg/ministack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Testcontainers Module
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.ministack&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;testcontainers-ministack&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;0.1.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;test&lt;span class="nt"&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Testcontainers&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;S3IntegrationTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Container&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;MiniStackContainer&lt;/span&gt; &lt;span class="n"&gt;ministack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MiniStackContainer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ministackorg/ministack:latest"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;shouldCreateBucketAndPutObject&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;S3Client&lt;/span&gt; &lt;span class="n"&gt;s3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;S3Client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;endpointOverride&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ministack&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEndpoint&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;credentialsProvider&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ministack&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCredentialsProvider&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Region&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;US_EAST_1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;s3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createBucket&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bucket&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test-bucket"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="n"&gt;s3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;putObject&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bucket&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test-bucket"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello.txt"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
                &lt;span class="nc"&gt;RequestBody&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fromString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello MiniStack!"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getObjectAsBytes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bucket&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test-bucket"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello.txt"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;asUtf8String&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello MiniStack!"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Works with JUnit 5 and Spring Boot's &lt;code&gt;@DynamicPropertySource&lt;/code&gt;. The container starts in under 2 seconds.&lt;/p&gt;




&lt;h2&gt;
  
  
  AWS CLI Bundled (v1.2.9)
&lt;/h2&gt;

&lt;p&gt;The Docker image now ships with AWS CLI v1. Init scripts just work without any credential configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# ready.d/01-create-resources.sh&lt;/span&gt;
aws s3 mb s3://my-bucket
aws sqs create-queue &lt;span class="nt"&gt;--queue-name&lt;/span&gt; my-queue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ready.d/02-seed-data.py
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="n"&gt;s3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;s3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;endpoint_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AWS_ENDPOINT_URL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Bucket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my-bucket&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;config.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;env&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;local&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both &lt;code&gt;.sh&lt;/code&gt; and &lt;code&gt;.py&lt;/code&gt; init scripts are supported. &lt;code&gt;AWS_ACCESS_KEY_ID&lt;/code&gt;, &lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;/code&gt;, &lt;code&gt;AWS_DEFAULT_REGION&lt;/code&gt;, and &lt;code&gt;AWS_ENDPOINT_URL&lt;/code&gt; are automatically set for init scripts.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Flea Hunt: 62 Bugs Found and Fixed
&lt;/h2&gt;

&lt;p&gt;We ran what we call a "Flea Hunt" — 2,490 tests across all 41 services using 10 parallel MiniStack instances. Some highlights:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;S3 versioning&lt;/strong&gt; — &lt;code&gt;GetObject&lt;/code&gt; by &lt;code&gt;VersionId&lt;/code&gt; was returning the wrong version. Delete markers were missing entirely from &lt;code&gt;ListObjectVersions&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lambda&lt;/strong&gt; — internal &lt;code&gt;_request_id&lt;/code&gt; was leaking into handler events. &lt;code&gt;PublishVersion&lt;/code&gt; ARN was missing the &lt;code&gt;:version&lt;/code&gt; qualifier.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DynamoDB&lt;/strong&gt; — Go SDK v2 requires a CRC32 header on every response. Without it, the SDK throws an integrity error before your code sees anything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Java SDK v2&lt;/strong&gt; — &lt;code&gt;time.time()&lt;/code&gt; floats in scientific notation broke the timestamp parser across 14 services. Fixed with &lt;code&gt;int(time.time())&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EC2&lt;/strong&gt; — TagSpecifications were silently ignored on 11 create operations. DeleteVpc succeeded even with subnets attached.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After the fixes: &lt;strong&gt;1,327 regression tests (1,196 Python + 131 Java), zero failures.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Start
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Docker:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 4566:4566 ministackorg/ministack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Terraform:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;endpoints&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;s3&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"http://localhost:4566"&lt;/span&gt;
    &lt;span class="nx"&gt;dynamodb&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"http://localhost:4566"&lt;/span&gt;
    &lt;span class="nx"&gt;sqs&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"http://localhost:4566"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;region&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;
  &lt;span class="nx"&gt;access_key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"test"&lt;/span&gt;
  &lt;span class="nx"&gt;secret_key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"test"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Website: &lt;a href="https://ministack.org" rel="noopener noreferrer"&gt;ministack.org&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/ministackorg/ministack" rel="noopener noreferrer"&gt;ministackorg/ministack&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Docker Hub: &lt;a href="https://hub.docker.com/r/ministackorg/ministack" rel="noopener noreferrer"&gt;ministackorg/ministack&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Maven Central: &lt;code&gt;org.ministack:testcontainers-ministack:0.1.0&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you give it a try, open an issue or tell us which service you want improved next.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;MiniStack is MIT licensed. Star us on GitHub if this saves you from mocking &lt;code&gt;AmazonS3Client&lt;/code&gt; one more time.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>docker</category>
      <category>aws</category>
      <category>python</category>
    </item>
    <item>
      <title>How we made Step Functions call any AWS service locally</title>
      <dc:creator>Nahuel Nucera</dc:creator>
      <pubDate>Tue, 07 Apr 2026 18:43:25 +0000</pubDate>
      <link>https://dev.to/nahuel990/how-we-made-step-functions-call-any-aws-service-locally-2m44</link>
      <guid>https://dev.to/nahuel990/how-we-made-step-functions-call-any-aws-service-locally-2m44</guid>
      <description>&lt;p&gt;If you've used AWS Step Functions, you know the &lt;code&gt;aws-sdk:*&lt;/code&gt; integration pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Task"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:states:::aws-sdk:dynamodb:PutItem"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"TableName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-table"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Item"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"pk"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"S.$"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$.id"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One line in your state machine, and Step Functions calls DynamoDB directly. No Lambda wrapper needed. AWS recommends this for all new workflows.&lt;/p&gt;

&lt;p&gt;The problem? Every local AWS emulator hardcodes service integrations. Want SQS? There's a handler. Want SNS? Another handler. Want SecretsManager? Sorry, not implemented yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  The generic dispatcher
&lt;/h2&gt;

&lt;p&gt;We added a generic &lt;code&gt;aws-sdk:*&lt;/code&gt; task dispatcher to MiniStack. Instead of writing a handler for each service, it routes to whatever service is already emulated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;arn:aws:states:::aws-sdk:secretsmanager:CreateSecret  → SecretsManager handler
arn:aws:states:::aws-sdk:dynamodb:PutItem              → DynamoDB handler  
arn:aws:states:::aws-sdk:ecs:RunTask                   → ECS handler
arn:aws:states:::aws-sdk:kms:Encrypt                   → KMS handler
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;38 services. All callable from Step Functions. No new code needed per service.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;The dispatcher:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Parses the ARN to extract service name and action&lt;/li&gt;
&lt;li&gt;Looks up the service in MiniStack's handler map&lt;/li&gt;
&lt;li&gt;Constructs the right headers (X-Amz-Target for JSON services)&lt;/li&gt;
&lt;li&gt;Converts PascalCase keys to the format each service expects&lt;/li&gt;
&lt;li&gt;Calls the handler and returns the result to the workflow&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For JSON-protocol services (DynamoDB, SecretsManager, ECS, KMS, CloudWatch Logs, SSM, EventBridge, Kinesis, Glue, Athena, ECR), it works today. Query and REST protocol services are coming.&lt;/p&gt;

&lt;h2&gt;
  
  
  What else ships with MiniStack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;38 AWS services&lt;/strong&gt; on a single port&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;1,047 integration tests&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;48 CloudFormation resource types&lt;/strong&gt; — CDK bootstrap + deploy works&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terraform VPC module&lt;/strong&gt; v6.6.0 fully compatible&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lambda&lt;/strong&gt; — Python, Node.js, Go/Rust/C++ (Docker), Docker images&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real infrastructure&lt;/strong&gt; — RDS spins up Postgres, ElastiCache runs Redis, ECS starts Docker containers&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 4566:4566 nahuelnucera/ministack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run your Step Functions workflow locally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;

&lt;span class="n"&gt;sfn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stepfunctions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;endpoint_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:4566&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;region_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us-east-1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;aws_access_key_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;aws_secret_access_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Your workflow can now call any of the 38 services
&lt;/span&gt;&lt;span class="n"&gt;sfn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_state_machine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my-workflow&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;definition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;...your ASL with aws-sdk integrations...&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;roleArn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;arn:aws:iam::000000000000:role/role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;MIT licensed. Free forever. &lt;a href="https://github.com/Nahuel990/ministack" rel="noopener noreferrer"&gt;github.com/Nahuel990/ministack&lt;/a&gt;&lt;/p&gt;

</description>
      <category>stepfunctions</category>
      <category>devops</category>
      <category>cicd</category>
      <category>aws</category>
    </item>
    <item>
      <title>Getting started testing AWS with MiniStack in under 10 minutes</title>
      <dc:creator>Nahuel Nucera</dc:creator>
      <pubDate>Sun, 05 Apr 2026 11:10:05 +0000</pubDate>
      <link>https://dev.to/nahuel990/getting-started-testing-aws-with-ministack-in-under-10-minutes-5787</link>
      <guid>https://dev.to/nahuel990/getting-started-testing-aws-with-ministack-in-under-10-minutes-5787</guid>
      <description>&lt;p&gt;You don't need an AWS account to test your AWS code.&lt;/p&gt;

&lt;p&gt;We just published an &lt;a href="https://ministack.org/getting-started.html" rel="noopener noreferrer"&gt;AWS Testing 101 guide&lt;/a&gt; — a step-by-step tutorial that takes you from zero to testing S3, DynamoDB, SQS, and Lambda on your laptop. No credentials, no cloud costs, no cleanup.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Every developer who writes AWS code hits this wall:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"I don't want to create resources in a real AWS account just to test"&lt;/li&gt;
&lt;li&gt;"My CI pipeline needs AWS but I don't want to pay for it"&lt;/li&gt;
&lt;li&gt;"I accidentally left a DynamoDB table running and got billed"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The answer is a local AWS emulator. Run it on your machine, point your SDK at &lt;code&gt;localhost:4566&lt;/code&gt;, and your code thinks it's talking to AWS.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 4566:4566 nahuelnucera/ministack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. 35+ AWS services running locally.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the guide covers
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. S3 — Create buckets and upload files
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;

&lt;span class="n"&gt;s3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;s3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;endpoint_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:4566&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;aws_access_key_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;aws_secret_access_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;region_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us-east-1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_bucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Bucket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my-bucket&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Bucket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my-bucket&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hello.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, local AWS!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. DynamoDB — Create tables and query data
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;ddb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dynamodb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;endpoint_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:4566&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;aws_access_key_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;aws_secret_access_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;region_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us-east-1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;ddb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;TableName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;users&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;KeySchema&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AttributeName&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;userId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;KeyType&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HASH&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="n"&gt;AttributeDefinitions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AttributeName&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;userId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AttributeType&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;S&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="n"&gt;BillingMode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PAY_PER_REQUEST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;ddb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TableName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;users&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;userId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;S&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user-001&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;S&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. SQS — Send and receive messages
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;sqs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sqs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;endpoint_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:4566&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;aws_access_key_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;aws_secret_access_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;region_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us-east-1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_queue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QueueName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my-queue&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;sqs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QueueUrl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;QueueUrl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;MessageBody&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello from SQS!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;msgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;receive_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;QueueUrl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;QueueUrl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msgs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  &lt;span class="c1"&gt;# Hello from SQS!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Lambda — Deploy and invoke functions
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;zipfile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;

&lt;span class="c1"&gt;# Package a function
&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;BytesIO&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;zipfile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ZipFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;zf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;zf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writestr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;index.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;def handler(event, ctx): return {&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello from Lambda!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;lam&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lambda&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;endpoint_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:4566&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;aws_access_key_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;aws_secret_access_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;region_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us-east-1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;lam&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;FunctionName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my-function&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Runtime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;python3.12&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Handler&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;index.handler&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;arn:aws:iam::000000000000:role/fake-role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ZipFile&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getvalue&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lam&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FunctionName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my-function&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Payload&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;  &lt;span class="c1"&gt;# {"message": "Hello from Lambda!"}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No AWS account needed&lt;/strong&gt; — test on day one&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No cost&lt;/strong&gt; — run thousands of operations for free&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No cleanup&lt;/strong&gt; — stop the container, everything's gone&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CI/CD ready&lt;/strong&gt; — same Docker image in GitHub Actions, GitLab CI, Jenkins&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terraform compatible&lt;/strong&gt; — point your provider at localhost:4566&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The full guide
&lt;/h2&gt;

&lt;p&gt;The complete tutorial with more examples and explanations is at:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://ministack.org/getting-started.html" rel="noopener noreferrer"&gt;ministack.org/getting-started.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MiniStack is the best alternative to LocalStack, it's open-source, MIT licensed, and free forever: &lt;a href="https://github.com/Nahuel990/ministack" rel="noopener noreferrer"&gt;github.com/Nahuel990/ministack&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 4566:4566 nahuelnucera/ministack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One command. 35+ services. Zero cost.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>docker</category>
      <category>cloud</category>
    </item>
    <item>
      <title>MiniStack vs Floci vs LocalStack: Honest Performance Benchmark (April 3rd 2026)</title>
      <dc:creator>Nahuel Nucera</dc:creator>
      <pubDate>Fri, 03 Apr 2026 19:57:59 +0000</pubDate>
      <link>https://dev.to/nahuel990/ministack-vs-floci-vs-localstack-honest-performance-benchmark-april-3rd-2026-479p</link>
      <guid>https://dev.to/nahuel990/ministack-vs-floci-vs-localstack-honest-performance-benchmark-april-3rd-2026-479p</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;We ran 30 API operations, throughput tests, and service coverage checks against real Docker containers. No cherry-picking. No marketing. Just numbers.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;MiniStack&lt;/th&gt;
&lt;th&gt;Floci&lt;/th&gt;
&lt;th&gt;LocalStack Free&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Services supported&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;31&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;~15 (rest paywalled)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Image size&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;211 MB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;276 MB&lt;/td&gt;
&lt;td&gt;~1 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory after load&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;39 MB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;56 MB&lt;/td&gt;
&lt;td&gt;~500 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Startup time&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&amp;lt;2s&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~3s&lt;/td&gt;
&lt;td&gt;~15-30s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Median API latency&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4.6 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;5.2 ms&lt;/td&gt;
&lt;td&gt;varies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;License&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;MIT&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;MIT&lt;/td&gt;
&lt;td&gt;BSL (restricted)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Methodology
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fresh &lt;code&gt;docker system prune -af --volumes&lt;/code&gt; before each run&lt;/li&gt;
&lt;li&gt;Both images pulled from Docker Hub (&lt;code&gt;nahuelnucera/ministack:latest&lt;/code&gt;, &lt;code&gt;hectorvent/floci:latest&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Each operation run &lt;strong&gt;5 times&lt;/strong&gt;, median taken&lt;/li&gt;
&lt;li&gt;All tests use boto3 with &lt;code&gt;endpoint_url=http://localhost:{port}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Machine: Apple Silicon M4, 24 GB RAM, Docker Desktop&lt;/li&gt;
&lt;li&gt;No warm-up runs — cold container, first request measured&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Image Size
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nahuelnucera/ministack:latest    211 MB
hectorvent/floci:latest          276 MB
localstack/localstack:latest    ~1.0 GB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;MiniStack is 24% smaller than Floci and 5x smaller than LocalStack. MiniStack uses Alpine + Python + Node.js. Floci uses a JVM-based stack.&lt;/p&gt;




&lt;h2&gt;
  
  
  Startup Time
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;First Response&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;MiniStack&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1 ms&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Floci&lt;/td&gt;
&lt;td&gt;15 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LocalStack&lt;/td&gt;
&lt;td&gt;15-30 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;MiniStack starts instantly. No JVM warm-up, no class loading. The ASGI server is ready before the health check even fires.&lt;/p&gt;




&lt;h2&gt;
  
  
  API Latency (median of 5 runs, single operation)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  S3
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Floci&lt;/th&gt;
&lt;th&gt;MiniStack&lt;/th&gt;
&lt;th&gt;Difference&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CreateBucket&lt;/td&gt;
&lt;td&gt;5.9 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;5.6 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;-5%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PutObject (1 KB)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;6.3 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;6.4 ms&lt;/td&gt;
&lt;td&gt;+2%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PutObject (100 KB)&lt;/td&gt;
&lt;td&gt;10.6 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;7.3 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;-31%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GetObject&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4.8 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;5.4 ms&lt;/td&gt;
&lt;td&gt;+13%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ListObjectsV2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;5.5 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;6.2 ms&lt;/td&gt;
&lt;td&gt;+13%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;S3 is competitive. Floci edges ahead on small reads. MiniStack is significantly faster on larger writes (100 KB: 31% faster).&lt;/p&gt;

&lt;h3&gt;
  
  
  SQS
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Floci&lt;/th&gt;
&lt;th&gt;MiniStack&lt;/th&gt;
&lt;th&gt;Difference&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CreateQueue&lt;/td&gt;
&lt;td&gt;4.5 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4.4 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;-2%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SendMessage&lt;/td&gt;
&lt;td&gt;9.8 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;8.3 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;-15%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ReceiveMessage&lt;/td&gt;
&lt;td&gt;7.8 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;6.5 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;-17%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;MiniStack is consistently faster on SQS operations.&lt;/p&gt;

&lt;h3&gt;
  
  
  DynamoDB
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Floci&lt;/th&gt;
&lt;th&gt;MiniStack&lt;/th&gt;
&lt;th&gt;Difference&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CreateTable&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.7 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3.4 ms&lt;/td&gt;
&lt;td&gt;-8%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PutItem&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.7 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4.2 ms&lt;/td&gt;
&lt;td&gt;+14%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GetItem&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.8 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4.4 ms&lt;/td&gt;
&lt;td&gt;+16%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Query&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4.3 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;5.0 ms&lt;/td&gt;
&lt;td&gt;+16%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scan&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4.2 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4.6 ms&lt;/td&gt;
&lt;td&gt;+10%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Floci wins on DynamoDB read/write operations. This is likely due to Java's optimized JSON parsing for the DynamoDB wire format.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other Services
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Floci&lt;/th&gt;
&lt;th&gt;MiniStack&lt;/th&gt;
&lt;th&gt;Difference&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SNS CreateTopic&lt;/td&gt;
&lt;td&gt;3.9 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.8 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;-3%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SNS Publish&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;8.5 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;8.8 ms&lt;/td&gt;
&lt;td&gt;+4%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IAM CreateRole&lt;/td&gt;
&lt;td&gt;5.0 ms&lt;/td&gt;
&lt;td&gt;5.9 ms&lt;/td&gt;
&lt;td&gt;+18%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;STS GetCallerIdentity&lt;/td&gt;
&lt;td&gt;5.1 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4.5 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;-12%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSM PutParameter&lt;/td&gt;
&lt;td&gt;6.6 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4.7 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;-29%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSM GetParameter&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4.7 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;5.2 ms&lt;/td&gt;
&lt;td&gt;+11%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SecretsManager Create&lt;/td&gt;
&lt;td&gt;4.8 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4.4 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;-8%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SecretsManager Get&lt;/td&gt;
&lt;td&gt;4.7 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4.4 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;-6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EventBridge PutRule&lt;/td&gt;
&lt;td&gt;5.3 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4.7 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;-11%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EventBridge PutEvents&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4.8 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;5.5 ms&lt;/td&gt;
&lt;td&gt;+15%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kinesis CreateStream&lt;/td&gt;
&lt;td&gt;5.6 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;5.1 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;-9%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CW PutMetricData&lt;/td&gt;
&lt;td&gt;4.9 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4.4 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;-10%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Logs CreateLogGroup&lt;/td&gt;
&lt;td&gt;6.5 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4.6 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;-29%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Route53 CreateHostedZone&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;ERR&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4.3 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Floci doesn't support Route53&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;MiniStack is faster on SSM, SecretsManager, CloudWatch, and Logs. Floci is faster on IAM and EventBridge PutEvents. Route53 only works on MiniStack.&lt;/p&gt;




&lt;h2&gt;
  
  
  Throughput
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test&lt;/th&gt;
&lt;th&gt;Floci&lt;/th&gt;
&lt;th&gt;MiniStack&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SQS SendMessage x500&lt;/td&gt;
&lt;td&gt;221 ops/s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;233 ops/s&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;On sustained SQS throughput, MiniStack is 5% faster. Earlier cold-start benchmarks showed Floci ahead, but with warm containers the gap disappears.&lt;/p&gt;




&lt;h2&gt;
  
  
  Memory Usage
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;State&lt;/th&gt;
&lt;th&gt;Floci&lt;/th&gt;
&lt;th&gt;MiniStack&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;At idle&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;26 MB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;38 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;After 500+ operations&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;56 MB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;39 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Interesting: Floci uses less memory at idle (JVM lazy class loading) but grows to 56 MB after load. MiniStack starts at 38 MB and barely grows. Over time, MiniStack's memory profile is more predictable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Service Coverage
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Floci&lt;/th&gt;
&lt;th&gt;MiniStack&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;S3&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SQS&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SNS&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DynamoDB&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lambda&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IAM&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;STS&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SecretsManager&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CloudWatch Logs&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSM&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EventBridge&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kinesis&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CloudWatch Metrics&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Step Functions&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cognito&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RDS&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CloudFormation&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ACM&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;KMS&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ECS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;NO&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;YES&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ElastiCache&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;NO&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;YES&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Glue&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;NO&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;YES&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Athena&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;NO&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;YES&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Firehose&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;NO&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;YES&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Route53&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;NO&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;YES&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;EC2/VPC&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;NO&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;YES&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;EMR&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;NO&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;YES&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ELBv2/ALB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;NO&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;YES&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;WAF v2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;NO&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;YES&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ECR&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;NO&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;YES&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;31&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;MiniStack supports 55% more services. The gap is particularly significant for infrastructure-heavy workloads (ECS, RDS with real Docker, EC2/VPC, Route53, ALB).&lt;/p&gt;




&lt;h2&gt;
  
  
  Feature Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;MiniStack&lt;/th&gt;
&lt;th&gt;Floci&lt;/th&gt;
&lt;th&gt;LocalStack Free&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Lambda Python execution&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lambda Node.js execution&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;NO&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lambda warm workers&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;NO&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RDS real Postgres/MySQL&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;NO (Pro)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ECS real Docker containers&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;NO&lt;/td&gt;
&lt;td&gt;NO (Pro)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ElastiCache real Redis&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;NO&lt;/td&gt;
&lt;td&gt;NO (Pro)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Athena real SQL (DuckDB)&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;NO&lt;/td&gt;
&lt;td&gt;NO (Pro)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CloudFormation&lt;/td&gt;
&lt;td&gt;YES (12 types)&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Step Functions TestState API&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;NO&lt;/td&gt;
&lt;td&gt;NO&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SFN Mock Config (SFN Local compat)&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;NO&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;State persistence&lt;/td&gt;
&lt;td&gt;YES (20 services)&lt;/td&gt;
&lt;td&gt;NO&lt;/td&gt;
&lt;td&gt;Partial&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;S3 disk persistence&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Detached mode (&lt;code&gt;-d&lt;/code&gt; / &lt;code&gt;--stop&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;NO&lt;/td&gt;
&lt;td&gt;NO&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Terraform v6 compatible&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;Partial&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS SDK v2 chunked encoding&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;NO&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Testcontainers examples&lt;/td&gt;
&lt;td&gt;Java, Go, Python&lt;/td&gt;
&lt;td&gt;NO&lt;/td&gt;
&lt;td&gt;Java&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;docker run&lt;/code&gt; one-liner&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PyPI installable&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;td&gt;NO&lt;/td&gt;
&lt;td&gt;YES&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  What Floci Does Better
&lt;/h2&gt;

&lt;p&gt;Let's be honest about where Floci wins:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;DynamoDB read latency&lt;/strong&gt; — 15-16% faster on GetItem/Query/Scan. Java's JSON processing is well-optimized for DynamoDB's wire format.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Idle memory&lt;/strong&gt; — 26 MB vs 38 MB at cold start. JVM defers class loading.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  What MiniStack Does Better
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;11 more services&lt;/strong&gt; — ECS, ElastiCache, Glue, Athena, Route53, EC2, EMR, ALB, WAF, Firehose, ECR.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real infrastructure&lt;/strong&gt; — RDS spins up actual Postgres/MySQL. ECS runs real containers. Athena runs real SQL via DuckDB.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lambda Node.js&lt;/strong&gt; — warm worker pool for both Python and Node.js.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State persistence&lt;/strong&gt; — 20 services survive restarts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Faster on most operations&lt;/strong&gt; — SSM, SecretsManager, SQS, CloudWatch, Logs are 15-30% faster.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terraform v6 ready&lt;/strong&gt; — EC2 stubs, S3 Control routing, DynamoDB WarmThroughput.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smaller image&lt;/strong&gt; — 211 MB vs 276 MB (24% smaller).&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  When to Use What
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Use MiniStack if:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need ECS, Route53, EC2, Glue, Athena, ALB, or any of the 11 extra services&lt;/li&gt;
&lt;li&gt;You're migrating from LocalStack and need maximum service coverage&lt;/li&gt;
&lt;li&gt;You want state persistence across container restarts&lt;/li&gt;
&lt;li&gt;You use Terraform v6&lt;/li&gt;
&lt;li&gt;You want Lambda Node.js support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use Floci if:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You only need the core 20 services&lt;/li&gt;
&lt;li&gt;DynamoDB read performance is critical for your test suite&lt;/li&gt;
&lt;li&gt;You want the smallest possible idle memory footprint&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use LocalStack Pro if:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need IAM policy enforcement&lt;/li&gt;
&lt;li&gt;You need Lambda container image support&lt;/li&gt;
&lt;li&gt;Budget isn't a constraint&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Benchmark Reproducibility
&lt;/h2&gt;

&lt;p&gt;All benchmarks can be reproduced with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker system prune &lt;span class="nt"&gt;-af&lt;/span&gt; &lt;span class="nt"&gt;--volumes&lt;/span&gt;
docker pull nahuelnucera/ministack:latest
docker pull hectorvent/floci:latest

docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; ms &lt;span class="nt"&gt;-p&lt;/span&gt; 4568:4566 nahuelnucera/ministack:latest
docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; fl &lt;span class="nt"&gt;-p&lt;/span&gt; 4567:4566 hectorvent/floci:latest

&lt;span class="c"&gt;# Run your own boto3 tests against both ports&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Versions Tested
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;MiniStack: v1.1.27 (April 2026)&lt;/li&gt;
&lt;li&gt;Floci: latest (April 2026)&lt;/li&gt;
&lt;li&gt;LocalStack: comparison based on published documentation (not benchmarked directly)&lt;/li&gt;
&lt;li&gt;boto3: 1.34+&lt;/li&gt;
&lt;li&gt;Docker Desktop: latest&lt;/li&gt;
&lt;li&gt;Hardware: Apple M4, 24 GB RAM&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;This benchmark was created by the MiniStack team. We tried to be as fair as possible — if you find any methodology issues, please open an issue on &lt;a href="https://github.com/Nahuel990/ministack" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>aws</category>
      <category>testing</category>
    </item>
    <item>
      <title>Ministack, the best alternative to Localstack</title>
      <dc:creator>Nahuel Nucera</dc:creator>
      <pubDate>Mon, 30 Mar 2026 19:18:13 +0000</pubDate>
      <link>https://dev.to/nahuel990/ministack-the-best-alternative-to-localstack-4553</link>
      <guid>https://dev.to/nahuel990/ministack-the-best-alternative-to-localstack-4553</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F979z720qvr8qm4u3zvbh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F979z720qvr8qm4u3zvbh.png" alt="Ministack, the best alternative to Localstack" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  We built a free LocalStack alternative — after last week’s changes
&lt;/h2&gt;

&lt;p&gt;Last week, LocalStack moved more core services behind a paywall.&lt;/p&gt;

&lt;p&gt;For a lot of teams, that quietly broke something important:&lt;/p&gt;

&lt;p&gt;👉 local AWS development that &lt;em&gt;just worked&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So we decided to build something about it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Introducing MiniStack
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;MiniStack&lt;/strong&gt; is a free, open-source AWS emulator designed for local development and CI/CD.&lt;/p&gt;

&lt;p&gt;It just got featured as &lt;em&gt;Project of the Day&lt;/em&gt; on aidigitalcrew.com 🙌&lt;/p&gt;




&lt;h2&gt;
  
  
  What started small grew fast
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;30 AWS services
&lt;/li&gt;
&lt;li&gt;~2s startup time
&lt;/li&gt;
&lt;li&gt;~30MB RAM at idle
&lt;/li&gt;
&lt;li&gt;Single port (&lt;code&gt;:4566&lt;/code&gt;)
&lt;/li&gt;
&lt;li&gt;600+ integration tests
&lt;/li&gt;
&lt;li&gt;MIT licensed (fully free)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The key difference: real infrastructure
&lt;/h2&gt;

&lt;p&gt;MiniStack doesn’t just mock APIs where it matters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;RDS&lt;/strong&gt; → spins up real Postgres/MySQL containers
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ElastiCache&lt;/strong&gt; → runs real Redis
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ECS&lt;/strong&gt; → starts real Docker containers
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Athena&lt;/strong&gt; → executes real SQL via DuckDB
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 No fake endpoints. No stubbed responses.&lt;/p&gt;




&lt;h2&gt;
  
  
  Services that are now paid elsewhere — free here
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;EC2 (instances, VPCs, networking)
&lt;/li&gt;
&lt;li&gt;EMR (clusters, steps)
&lt;/li&gt;
&lt;li&gt;Cognito (user + identity pools)
&lt;/li&gt;
&lt;li&gt;EBS / EFS
&lt;/li&gt;
&lt;li&gt;ALB / ELBv2
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Same developer experience
&lt;/h2&gt;

&lt;p&gt;If you’ve used LocalStack before, nothing changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 4566:4566 nahuelnucera/ministack

aws &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4566 s3 mb s3://my-bucket
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;No account
&lt;/li&gt;
&lt;li&gt;No API key
&lt;/li&gt;
&lt;li&gt;No telemetry
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why we built this
&lt;/h2&gt;

&lt;p&gt;This isn’t about competing.&lt;/p&gt;

&lt;p&gt;LocalStack is a great product.&lt;/p&gt;

&lt;p&gt;But local development tooling should be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fast
&lt;/li&gt;
&lt;li&gt;predictable
&lt;/li&gt;
&lt;li&gt;accessible
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;⭐ &lt;a href="https://github.com/Nahuel990/ministack" rel="noopener noreferrer"&gt;https://github.com/Nahuel990/ministack&lt;/a&gt;&lt;br&gt;
⭐ &lt;a href="https://ministack.org" rel="noopener noreferrer"&gt;https://ministack.org&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Would love feedback, ideas, or contributions from the community.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>terraform</category>
      <category>python</category>
      <category>aws</category>
    </item>
    <item>
      <title>MiniStack v1.1.2 — Cognito, EC2, EMR, 656 Tests, and Zero Docker Leaks</title>
      <dc:creator>Nahuel Nucera</dc:creator>
      <pubDate>Mon, 30 Mar 2026 04:57:48 +0000</pubDate>
      <link>https://dev.to/nahuel990/ministack-v110-cognito-ec2-emr-656-tests-and-zero-docker-leaks-2k3b</link>
      <guid>https://dev.to/nahuel990/ministack-v110-cognito-ec2-emr-656-tests-and-zero-docker-leaks-2k3b</guid>
      <description>&lt;p&gt;We just shipped MiniStack v1.1.2. This is the biggest release since the initial launch — full Amazon Cognito support, partial EC2, EMR, a complete test suite overhaul, and a pile of infrastructure fixes that make running MiniStack day-to-day significantly cleaner.&lt;/p&gt;

&lt;p&gt;If you're not familiar: MiniStack is a free, open-source local AWS emulator. One port, no account, no license key. A drop-in replacement for LocalStack — which moved its core services behind a paid plan.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's new in v1.1.0
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Amazon Cognito — full emulation
&lt;/h3&gt;

&lt;p&gt;This was the most requested feature since launch. v1.1.0 ships complete Cognito support across both planes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;User Pools (cognito-idp)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full user lifecycle: &lt;code&gt;SignUp&lt;/code&gt;, &lt;code&gt;ConfirmSignUp&lt;/code&gt;, &lt;code&gt;AdminCreateUser&lt;/code&gt;, &lt;code&gt;AdminDeleteUser&lt;/code&gt;, &lt;code&gt;AdminGetUser&lt;/code&gt;, &lt;code&gt;ListUsers&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Auth flows: &lt;code&gt;USER_PASSWORD_AUTH&lt;/code&gt;, &lt;code&gt;ADMIN_USER_PASSWORD_AUTH&lt;/code&gt;, &lt;code&gt;REFRESH_TOKEN_AUTH&lt;/code&gt;, &lt;code&gt;USER_SRP_AUTH&lt;/code&gt; (returns &lt;code&gt;PASSWORD_VERIFIER&lt;/code&gt; challenge)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;FORCE_CHANGE_PASSWORD&lt;/code&gt; challenge on first login&lt;/li&gt;
&lt;li&gt;Self-service: &lt;code&gt;ForgotPassword&lt;/code&gt;, &lt;code&gt;ConfirmForgotPassword&lt;/code&gt;, &lt;code&gt;ChangePassword&lt;/code&gt;, &lt;code&gt;GetUser&lt;/code&gt;, &lt;code&gt;DeleteUser&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Groups, domains, MFA config, tags — all covered&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Identity Pools (cognito-identity)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CreateIdentityPool&lt;/code&gt;, &lt;code&gt;GetId&lt;/code&gt;, &lt;code&gt;GetCredentialsForIdentity&lt;/code&gt;, &lt;code&gt;GetOpenIdToken&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SetIdentityPoolRoles&lt;/code&gt;, &lt;code&gt;GetIdentityPoolRoles&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Federated identity: &lt;code&gt;MergeDeveloperIdentities&lt;/code&gt;, &lt;code&gt;UnlinkIdentity&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;OAuth2&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;POST /oauth2/token&lt;/code&gt; — client_credentials flow, returns stub Bearer token&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stub JWTs are structurally valid base64url tokens — they pass format checks in most SDKs without needing real crypto.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;

&lt;span class="n"&gt;idp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cognito-idp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;endpoint_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:4566&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="n"&gt;aws_access_key_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;aws_secret_access_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="n"&gt;region_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us-east-1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Create a pool
&lt;/span&gt;&lt;span class="n"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;idp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_user_pool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PoolName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my-app&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;pool_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;UserPool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Sign up a user
&lt;/span&gt;&lt;span class="n"&gt;idp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sign_up&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ClientId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;local&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;alice@example.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Password123!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;UserAttributes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Value&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;alice@example.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Confirm and authenticate
&lt;/span&gt;&lt;span class="n"&gt;idp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;admin_confirm_sign_up&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UserPoolId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;pool_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;alice@example.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;idp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initiate_auth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;AuthFlow&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;USER_PASSWORD_AUTH&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;AuthParameters&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;USERNAME&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;alice@example.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PASSWORD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Password123!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;ClientId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;local&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AuthenticationResult&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AccessToken&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  644 tests — one file, all passing
&lt;/h3&gt;

&lt;p&gt;We merged a separate QA test file into the main suite and fixed every test bug we found along the way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;test_s3_list_v1_marker_pagination&lt;/code&gt; — &lt;code&gt;NextMarker&lt;/code&gt; only returned when &lt;code&gt;Delimiter&lt;/code&gt; is set (AWS spec)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;test_iam_inline_user_policy&lt;/code&gt; — boto3 deserialises &lt;code&gt;PolicyDocument&lt;/code&gt; as a dict, not a string&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;test_kinesis_at_timestamp_iterator&lt;/code&gt; — boto3 already returns &lt;code&gt;Data&lt;/code&gt; as &lt;code&gt;bytes&lt;/code&gt;, no need to base64-decode&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;test_rds_snapshot_crud&lt;/code&gt; / &lt;code&gt;test_rds_deletion_protection&lt;/code&gt; — added &lt;code&gt;finally&lt;/code&gt; cleanup so containers are deleted after each test&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;644 tests across all 25 services. Single file. All passing.&lt;/p&gt;




&lt;h3&gt;
  
  
  Docker volume leak — fixed
&lt;/h3&gt;

&lt;p&gt;This one was subtle. Every RDS (&lt;code&gt;CreateDBInstance&lt;/code&gt;) and ElastiCache (&lt;code&gt;CreateCacheCluster&lt;/code&gt;) call spins up a real Docker container. The postgres and mysql images declare &lt;code&gt;VOLUME /var/lib/postgresql/data&lt;/code&gt; — so Docker was creating an anonymous volume for every container, even after the container was removed.&lt;/p&gt;

&lt;p&gt;After 20 test runs: 30+ dangling volumes, 600MB+ of wasted space.&lt;/p&gt;

&lt;p&gt;Two fixes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;tmpfs&lt;/code&gt;&lt;/strong&gt; on &lt;code&gt;containers.run()&lt;/code&gt; — postgres/mysql data lives in container RAM. No volume created.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;container.remove(v=True)&lt;/code&gt;&lt;/strong&gt; in &lt;code&gt;reset()&lt;/code&gt; — volumes are removed with the container.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Before: 32 dangling volumes after 3 test runs
After:  2 volumes total (ministack + redis, always)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clean up what you already have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;make purge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;code&gt;make purge&lt;/code&gt; — safe cleanup
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;purge&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;stop-compose&lt;/span&gt;
    docker &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="p"&gt;$(&lt;/span&gt;docker ps &lt;span class="nt"&gt;-aq&lt;/span&gt; &lt;span class="nt"&gt;--filter&lt;/span&gt; &lt;span class="s2"&gt;"label=ministack"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 2&amp;gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;
    docker volume prune &lt;span class="nt"&gt;-f&lt;/span&gt;
    &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; ./data/s3/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every container MiniStack spins up is labelled &lt;code&gt;ministack=true&lt;/code&gt;. The purge target uses that label — it won't touch your other Redis, Postgres, or MySQL containers.&lt;/p&gt;




&lt;h3&gt;
  
  
  Bug fixes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lambda &lt;code&gt;GetFunctionConcurrency&lt;/code&gt;&lt;/strong&gt; — was returning 404 after &lt;code&gt;DeleteFunctionConcurrency&lt;/code&gt;. Now returns &lt;code&gt;{}&lt;/code&gt; matching AWS behaviour&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ElastiCache &lt;code&gt;ModifyCacheParameterGroup&lt;/code&gt;&lt;/strong&gt; — parameter key format was wrong (&lt;code&gt;member&lt;/code&gt; vs &lt;code&gt;ParameterNameValue&lt;/code&gt;). Modified params were silently ignored&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RDS &lt;code&gt;ModifyDBInstance&lt;/code&gt;&lt;/strong&gt; — &lt;code&gt;DeletionProtection=False&lt;/code&gt; with &lt;code&gt;ApplyImmediately=True&lt;/code&gt; now correctly applies immediately&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cognito &lt;code&gt;GetCredentialsForIdentity&lt;/code&gt;&lt;/strong&gt; — response field is &lt;code&gt;SecretKey&lt;/code&gt; (correct boto3 wire name)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Port conflict on &lt;code&gt;pip install&lt;/code&gt;&lt;/strong&gt; — &lt;code&gt;ministack&lt;/code&gt; now prints a clear error if port 4566 is already in use instead of a raw uvicorn traceback&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  AWS CLI docs fix
&lt;/h3&gt;

&lt;p&gt;A user reported credentials failing. The README was showing &lt;code&gt;aws configure --profile local&lt;/code&gt; but then omitting &lt;code&gt;--profile local&lt;/code&gt; from the example commands. Fixed — two working options now documented:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option A — environment variables&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;test
export &lt;/span&gt;&lt;span class="nv"&gt;AWS_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;test
export &lt;/span&gt;&lt;span class="nv"&gt;AWS_DEFAULT_REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;us-east-1

aws &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4566 s3 mb s3://my-bucket
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Option B — named profile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws configure &lt;span class="nt"&gt;--profile&lt;/span&gt; &lt;span class="nb"&gt;local&lt;/span&gt;
&lt;span class="c"&gt;# Access Key: test / Secret: test / Region: us-east-1&lt;/span&gt;

aws &lt;span class="nt"&gt;--profile&lt;/span&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4566 s3 mb s3://my-bucket
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Get it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# PyPI&lt;/span&gt;
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--upgrade&lt;/span&gt; ministack

&lt;span class="c"&gt;# Docker&lt;/span&gt;
docker pull nahuelnucera/ministack:latest
docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub: &lt;a href="https://github.com/Nahuel990/ministack" rel="noopener noreferrer"&gt;github.com/Nahuel990/ministack&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;25 AWS services. Free. MIT licensed. No account required.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SFN Activities&lt;/strong&gt; (&lt;code&gt;CreateActivity&lt;/code&gt;, &lt;code&gt;GetActivityTask&lt;/code&gt;) — already requested&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State persistence&lt;/strong&gt; for Secrets Manager, SSM, DynamoDB — &lt;code&gt;PERSIST_STATE=1&lt;/code&gt; currently only covers API Gateway&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ACM&lt;/strong&gt; — last item on the original roadmap&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Issues and PRs welcome.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>python</category>
      <category>development</category>
      <category>ec2</category>
    </item>
  </channel>
</rss>
