Guides, changelogs, and community highlights for the free LocalStack alternative.
.github/workflows/ file that runs your AWS tests on every push.GetLogEvents / FilterLogEvents now accept logGroupIdentifier (either a bare group name or a full arn:aws:logs:<region>:<account>:log-group:<name>[:*] ARN) in addition to logGroupName — calls passing an ARN no longer fail with ResourceNotFoundException: The specified log group does not exist: None. ElastiCache DescribeCacheClusters per-node XML now includes CacheNodeCreateTime (ISO8601), ParameterGroupStatus, CustomerAvailabilityZone, and SourceCacheNodeId, so hashicorp/terraform-provider-aws v6.45.0's read of CacheNodeCreateTime stops crashing with Unexpected nil pointer in: {CacheNodeCreateTime:<nil> ...}. API Gateway v1 UpdateStage now coerces the patch value string to bool for tracingEnabled and cacheClusterEnabled (AWS sends every patch value as a string, but the SDK v2 deserializer expects *bool on the response) — exact path match so a stage variable named tracingEnabled is unaffected.$uppercase, $lowercase, $substring, $trim, $contains, $split, $join, $replace, $pad), numeric ($sum, $average, $max, $min, $abs, $floor, $ceil, $round, $power, $sqrt, $formatNumber), array ($sort with comparator-function form, $reverse, $distinct, $append), object ($keys, $values, $lookup over both objects and arrays-of-objects, $exists), type ($type, $boolean), date/time ($now()/$now(picture)/$now(picture, timezone), $millis), and utility ($uuid, $base64encode, $base64decode). $contains/$split/$replace accept JSONata regex literals (/pattern/flags); $exists now distinguishes a missing path from an explicit null. The motivating "Condition": "{% $exists($states.input.userId) %}" in Choice routes correctly in every case. Implemented natively in Python with no new runtime dependency. RDS Data API stops silently acking writes against a still-booting container — container-backed clusters whose endpoint can't be reached now surface DatabaseUnavailableException (HTTP 504) instead of falling through to the in-memory SQL stub. CreateDBInstance returns immediately with status=creating matching real AWS — readiness finalisation runs on a daemon thread, no wall-clock timeout, transitions to available or failed based on container liveness. ECS RunTask containers now carry the five canonical com.amazonaws.ecs.* labels real ECS sets (cluster ARN, container-name, task-arn, task-definition-family, task-definition-version), so host-side agents identify them the same way they would against real ECS.DescribeEndpoint on the control plane, MQTT 3.1.1 over WebSocket on the gateway port plus HTTP iot-data Publish on the data plane. Persistent sessions, QoS 1 with DUP-flag retransmits, Last Will and Testament, retained messages, multi-tenancy via account-prefixed topics — all per the MQTT 3.1.1 spec. Local CA cert at GET /_ministack/iot/ca.pem; CA + broker state persist across restarts. Requires cryptography (in [full]). Athena now resolves database.table references against Glue's GetTable so queries pick up table locations automatically, and completed query results persist to OutputLocation as <id>.csv (with the column-name header row, matching real Athena) plus a <id>.csv.metadata sidecar. DuckDB execution offloaded to a worker thread so the event loop stays free under concurrent queries. EventBridge rule targets pointing at arn:aws:states:...:stateMachine:<name> now actually dispatch — they were silently dropped before — passing the transformed event payload verbatim as the execution input.apache/airflow:<version> containers for both 2.x and 3.x — CreateEnvironment spawns a container in standalone mode, syncs DAGs from your S3 bucket into /opt/airflow/dags/, forces aggressive scan intervals so DAGs become visible in seconds, and InvokeRestApi proxies straight through to Airflow's REST API (auth handled transparently for both v2 basic-auth and v3 Simple Auth Manager). End-to-end verified with real DAGs visible on both apache/airflow:2.10.4 and apache/airflow:3.0.6. CloudWatch alarm actions now publish to SNS on every OK ↔ ALARM ↔ INSUFFICIENT_DATA transition with the AWS-shaped payload (NewStateValue, StateChangeTime, Trigger sub-object) — alerting-driven test scenarios work end-to-end. Lambda emits the four canonical AWS/Lambda metrics on every invocation (Invocations, Errors, Duration, Throttles), dimensioned by FunctionName; combined with the alarm-action fix, end-to-end Lambda observability tests (invoke → error → alarm fires → SNS notification arrives) work in one local run. CFN AWS::ApiGateway::Account closes the gap that blocked CDK new RestApi({ cloudWatchRole: true }) stacks with Unsupported resource type.Decrypt on a malformed CiphertextBlob without an explicit KeyId now returns InvalidCiphertextException (matches real AWS) instead of NotFoundException. The KeyId-given branch is unchanged — explicit-key-not-found still returns NotFoundException, also matching AWS. Wrapper libraries that catch encryption faults separately from key-lookup faults (retry on NotFound, surface InvalidCiphertext immediately) now see the same code locally as in production. Encrypt/Decrypt round-trips, asymmetric key paths (RSAES_OAEP_SHA_256, etc.), and every other KMS operation are untouched.AdminCreateUser, SignUp, ResendConfirmationCode, ForgotPassword, and AdminResetUserPassword all hand their welcome / temporary-password / verification messages to SES, so tests see them at /_ministack/ses/messages and they relay via SMTP when SMTP_HOST is set. MessageAction=SUPPRESS/RESEND, DesiredDeliveryMediums, InviteMessageTemplate / VerificationMessageTemplate placeholders, and the EmailConfiguration.From override all match AWS; ResendConfirmationCode ships alongside as a previously-missing action. Step Functions JSONata gains state-level Assign + execution-scoped variables: bind values to $name in any state, reference them in any later JSONata expression with dotted-path access, with States.QueryEvaluationError for undefined refs. Cognito sign-in honors AliasAttributes and UsernameAttributes — users can sign in by email, phone_number, or preferred_username (verification gate on email/phone, matching AWS), routed through every auth/verify call site. SQS RedrivePolicy is validated at CreateQueue / SetQueueAttributes — malformed values return 400 InvalidAttributeValue instead of crashing the queue's ReceiveMessage with InternalError. DynamoDB SET v = (if_not_exists(v, :d) - :amt) now actually subtracts (the outer parens used to hide the operator from the top-level scan). S3 → Lambda notifications fire for non-boto3 SDK clients: the XML parser accepts both the legacy <CloudFunction> tag (botocore wire form) and the modern <LambdaFunctionArn> tag (AWS SDK Java v2, Go SDK, Terraform, hand-crafted XML).Arguments and success/Catch Output against $states.input / $states.result / $states.errorOutput (was dispatching with empty payloads); Pass evaluates Output (was silently ignored); Choice evaluates per-branch Condition and per-branch Output (was always falling through to Default). The evaluator gained comparison, arithmetic, string concat (&), and/or/in, $count / $length / $not / $string / $number, paren grouping, and left-associative parsing. Step Functions executions no longer stall at ExecutionStarted under non-default 12-digit account IDs — the background worker now inherits the request's contextvars via copy_context().run, with per-thread snapshots at the Parallel and Map spawn sites. Cognito OIDC federation completes: /oauth2/idpresponse exchanges the IdP's code against its token_url, decodes the id_token, applies AttributeMapping, and provisions the federated user (SAML federation continues to use /saml2/idpresponse). Node.js Lambda handlers can now require('@aws-sdk/client-*') the same way real AWS-managed runtimes do — Lambda gets a dedicated REST stub, 28 awsJson1.x services resolve via a generic X-Amz-Target Proxy stub, errors expose err.name for the v3 catch-by-name convention, and the HTTPS→HTTP localhost downgrade now covers CDK Provider Framework's cfn-response.js PUT.AWS::CertificateManager::Certificate (every HTTPS IaC stack now applies); AWS::ElasticLoadBalancingV2::TargetGroup and AWS::ElasticLoadBalancingV2::ListenerRule (the ALB CFN story was previously partial — Listener had nothing to forward to); AWS::RDS::DBInstance (standalone DBs and Aurora cluster members, metadata-only like the existing DBCluster handler); and Step Functions Definition + DefinitionS3Location with DefinitionSubstitutions (so CDK's DefinitionBody.fromFile() stops producing InvalidDefinition: StartAt state 'None' not found). ECS task IAM role credentials endpoint at GET /v2/credentials/<uuid> with the AWS-strict 5-field shape (AccessKeyId, SecretAccessKey, Token, Expiration, RoleArn) — distinct from the IMDS endpoint at /latest/meta-data/iam/security-credentials/<role>. RunTask injects AWS_CONTAINER_CREDENTIALS_FULL_URI, AWS_CONTAINER_AUTHORIZATION_TOKEN, and AWS_ENDPOINT_URL so unmodified SDKs in the task work end-to-end. ECS connectivityAt/stoppingAt now wire as JSON numbers (Go SDK v2 strict parsing); CFN AWS::ECS::TaskDefinition populates registeredAt/registeredBy/compatibilities.AWS::ApiGateway::Authorizer (TOKEN / REQUEST / COGNITO_USER_POOLS) provisions instead of failing the stack. SQS AddPermission / RemovePermission wire through to the queue's Policy attribute in AWS-canonical shape (bare account ID in Principal.AWS, lowercase sqs: action prefix). RDS DescribePendingMaintenanceActions accepts the call and returns an empty list. Six AWS-parity correctness fixes: SQS SendMessage validates body against MaximumMessageSize (was silently accepting oversized); SNS Publish/PublishBatch enforce the 256 KiB Message+Attributes limit; EventBridge SQS targets now stamp SqsParameters.MessageGroupId on FIFO queues (was dropped at dispatch); SQS DeleteQueue raises QueueDoesNotExist for missing queues (was silently 200); S3 UploadPartCopy validates x-amz-copy-source-range (malformed values were 500, reversed/out-of-bounds were silent 200s); S3 _parse_bucket_key strips absolute-form request targets (AWS SDK for .NET v4 was hitting NoSuchBucket: http:).arn:aws:iam::aws:policy/<Name>) now resolve from any session account, pre-seeded with 20 of the most-referenced canonical documents (Administrator/PowerUser/ReadOnly/SecurityAudit, the AmazonS3/EC2/DynamoDB/SQS/SNS Full and ReadOnly variants, AWSLambdaBasicExecutionRole / VPCAccessExecutionRole, AmazonSSMManagedInstanceCore, AmazonECSTaskExecutionRolePolicy, CloudWatchAgentServerPolicy / LogsFullAccess, AWSCloudFormationFullAccess). Unknown AWS-managed ARNs return NoSuchEntity so typos surface locally; opt in to permissive autovivify with MINISTACK_AUTOCREATE_AWS_MANAGED=1. AttachmentCount is per-session-account. Full 7-operation Cost and Usage Reports service for IaC validation (no cost data emulation — Terraform / CDK / Bash that manages aws_cur_report_definition can now plan and apply locally). Lambda ruby4.0 wired to AWS's official base image (tracking botocore 1.42.94). RDS DescribeDBClusters serialization fixed for DatabaseName / NetworkType / EngineLifecycleSupport; DescribeDBClusterParameters emits <Source>. Two warm-boot persistence gaps closed (CUR was never loading state on import; IAM AttachmentCount sidecar was missing from get_state / restore_state).CreateCluster works again — the k3s server container is now launched with privileged=True (k3s needs to remount /sys/fs/cgroup, which no granular capability set permits, so it was exiting on boot with failed to evacuate root cgroup). SNS FIFO topics can now subscribe standard SQS queues, matching AWS behaviour since 2023-09-14 — the stale validation that returned InvalidParameterException is removed. RDS CreateDBInstance now honours caller-supplied PreferredMaintenanceWindow instead of hardcoding sun:05:00-sun:06:00.docker push and docker pull against MiniStack work end-to-end: /v2/ ping, _catalog, chunked and single-shot blob uploads, cross-repo blob mounts, manifest PUT/GET/HEAD/DELETE, and tags/list. Pushed images show up immediately in aws ecr describe-images. CloudFormation Custom::* and AWS::CloudFormation::CustomResource resources run the full Create / Update / Delete lifecycle through a local /_ministack/cfn-response/{token} intercept — CDK cr.Provider Lambdas are now supported. Cognito OAuth2 id_token now echoes the client-supplied nonce per OIDC Core 1.0 §3.1.3.7.AWS::DynamoDB::GlobalTable — what CDK TableV2 emits — now provision in MiniStack. KeySchema, AttributeDefinitions, BillingMode, StreamSpecification, GSIs, LSIs, SSESpecification, TimeToLiveSpecification, TableName are honoured. For PROVISIONED billing, WriteProvisionedThroughputSettings.WriteCapacityAutoScalingSettings.MinCapacity (and the read counterpart) translate to static ProvisionedThroughput since the emulator doesn't simulate auto-scaling. Replicas, MultiRegionConsistency, GlobalTableWitnesses, GlobalTableSourceArn, WarmThroughput, and the on-demand throughput settings are accepted and ignored./.well-known/openid-configuration now returns reachable URLs at the MiniStack gateway (was pointing at cognito-idp.<region>.amazonaws.com URLs that don't serve OAuth2 anywhere); response_types_supported advertises both code and token per AWS. Cognito OAuth2 / OIDC endpoints (/oauth2/authorize, /oauth2/token, /oauth2/userInfo, /logout, /.well-known/*) now send wildcard CORS so Amplify, oidc-client-ts, and react-oidc-context work cross-origin. EC2 VPN Connection CRUD plus a DescribeRouteTables fix that emits propagatingVgwSet. EC2 RunInstances honours --private-ip-address and --iam-instance-profile (both were silently dropped; default IPs were malformed). DynamoDB GSI Query pagination now tiebreaks on the base table primary key, so ExclusiveStartKey doesn't drop or cycle items when the GSI sort key collides.AWS_ACCESS_KEY_ID from the function ARN (warm pool keyed per account), so STS GetCallerIdentity from inside the handler resolves to the owning tenant. EC2 RunInstances auto-attaches a root EBS volume so DescribeInstances emits BlockDeviceMappings matching real AWS — Cloud Custodian and AWS Config policies no longer break. S3 versioned GetObject emits RFC 7231 Last-Modified, fixing AWS SDK for JavaScript v3's strict header parser. EC2 AWS-managed prefix lists return deterministic CIDRs (s3, dynamodb, s3express, vpc-lattice, route53-healthchecks, ec2-instance-connect, cloudfront, groundstation) for Gateway-type VPC endpoints.aws-sdk integrations (e.g. aws-sdk:rdsdata:executeStatement) now expose output keys with the same PascalCase convention as the query and REST-XML dispatchers (Records, NumberOfRecordsUpdated) instead of raw camelCase wire keys, so ResultSelector paths like $.Records resolve correctly.DescribeVpcEndpointServices with the standard 2 Gateway + 17 Interface PrivateLink catalog. DynamoDB legacy AttributeUpdates (PUT / DELETE / ADD) for .NET SDK upserts. Step Functions aws-sdk:ec2 security-group dispatch now uses EC2-shaped Filter.1.Value.1 instead of generic member.N; aws-sdk:s3 integrations gain a REST-XML dispatcher covering ListBuckets, CreateBucket, DeleteBucket, HeadBucket, GetBucketVersioning, ListObjectsV2, ListObjects, HeadObject, CopyObject, DeleteObject, GetObjectTagging, PutObjectTagging. SQS ReceiveMessage honours the modern MessageSystemAttributeNames for AWS SDK v2 (Java/Kotlin). CFN AWS::SNS::Subscription honours RawMessageDelivery.RunTask gets ECS_CONTAINER_METADATA_URI_V4 injected, and the gateway serves /v4/<token>, /v4/<token>/task (with sibling Containers), and /stats. RunTask also translates privileged, linuxParameters.capabilities.add, pidMode: host, and volumes + mountPoints into Docker bind mounts. DynamoDB legacy Expected (PutItem / UpdateItem / DeleteItem) and KeyConditions (Query) now evaluated correctly with all 13 comparison operators and type-aware numeric compare. TransactWriteItems CancellationReasons now reports every failing item, not just the first.CLOUDTRAIL_RECORDING=1; all 8 LookupAttributes) and AWS Resource Groups (19 of 23 spec ops). Plus a sweep of AWS-spec parity fixes: API Gateway v1 GetUsagePlanKey / HTTP_PROXY path-param substitution / UpdateModel; Transfer Family LOGICAL root home directories; STS Credentials.Expiration int epoch; DynamoDB Item populated on ConditionalCheckFailedException when ReturnValuesOnConditionCheckFailure="ALL_OLD"; CloudFormation AWS::S3::Bucket physical-id preservation across stack updates; CloudFormation AWS::Lambda::Function returns real CodeSize and CodeSha256.s3files-2025-05-05) routes and shapes now match the published AWS spec end to end: PUT /file-systems (was POST), camelCase request/response bodies, /resource-tags/{resourceId} for tagging, PutSynchronizationConfiguration optimistic concurrency. OpenSearch non-VPC domains stop emitting empty VPCOptions alongside Endpoint, which was causing the Terraform AWS provider to misclassify the domain as VPC-backed and fail. CloudFormation AWS::CloudFront::KeyValueStore provisioning lands with in-place Comment update + ImportSource support on the native CloudFront API.aws-appsync-event-ws subprotocol) and CloudFront KeyValueStore (management plane + the separate cloudfront-keyvaluestore data-plane SDK service). EventBridge cron() now has full AWS-spec parity — L, LW, <n>W, <n>L, <n>#<k> operators and DoM/DoW mutual-exclusion enforced at PutRule. Plus 8 EventBridge AWS-spec divergences fixed (CreatedBy/ManagedBy, PutEvents 10-cap, int Time, exists:false on absent keys, ListRules pagination, opaque NextToken, omitted empty Policy, EventSource state enum).x-amzn-errortype response header that Java SDK v2, Go SDK v2, and Rust SDK read — without it they surface SdkClientException: unknown error type instead of the actual code. AppConfig 404 bodies include __type alongside the existing Code/Message. Three previously-stateless services (account, waf-classic, resourcegroupstaggingapi) expose a no-op reset() so /_ministack/reset no longer logs warnings.aws CLI. Write init scripts in Shell or Python with automatic credentials.