What's Changed
[1.5.9] — 2026-09-08
Added
- CloudFormation — a
WaitConditionwaits for its signals,SignalResourcedelivers them — the handle'sRefis now a URL the emulator serves (PUTthe AWS signal JSON with an emptyContent-Type); the wait condition holds the stack untilCountdistinct SUCCESS signals arrive, a FAILURE or theTimeoutrolls it back, signals are published to the stack events, andFn::GetAtt Wait.Datais the{UniqueId: Data}map. TheCreationPolicyform (ResourceSignal, defaultPT5M) is signalled through the newSignalResourceaction, by stack name or id. A nested stack now deploys on a worker thread, so a wait condition or custom resource inside it no longer blocks the server. Contributed by @iot-rocket. - CloudFormation — stack-level tags propagate, and the
Tagsproperty of the common types reaches the service — the 44 types with a tag property receive the stack tags and the threeaws:cloudformation:tags on create and update (a key the template sets wins);AWS::SQS::Queue,AWS::SNS::Topic,AWS::DynamoDB::Table,AWS::Lambda::Function,AWS::Logs::LogGroupandAWS::Kinesis::Streamnow store their ownTagswhere the service's list-tags call reads them. An emptyTagsonUpdateStackremoves them, more than 50 tags or anaws:key are refused, tags set through a service's own API survive stack updates, and a nested stack passes the tags on. Contributed by @iot-rocket. - CloudFormation —
ListImports,UpdateTerminationProtection,SetStackPolicy,GetStackPolicy,CancelUpdateStackandContinueUpdateRollback— the first four answeredInvalidAction, the last two did not exist, so anUPDATE_ROLLBACK_FAILEDstack had no way out. Termination protection makesDeleteStackrefuse,CancelUpdateStackstops a running update before its next resource ("User Initiated"), andContinueUpdateRollbackretries the failed deletes, honouringResourcesToSkip. Contributed by @iot-rocket. - CloudFormation — the list and describe actions page —
DescribeStacks,ListStacks,DescribeStackEvents,ListStackResources,ListExports,ListImportsandListChangeSetsreturned everything and ignoredNextToken; they now return 100 items per page with a token for the rest (ListExportspages at 100 values on AWS, the others at 1 MB), a foreign token is aValidationError, and events of one millisecond stay strictly newest-first across pages. Contributed by @iot-rocket. - CloudFormation — dynamic references resolve —
{{resolve:ssm:...}},{{resolve:ssm-secure:...}}and{{resolve:secretsmanager:...}}resolve at provisioning time against the in-process stores, with the version, JSON key and version-stage segments;GetTemplatekeeps the literal. On update anssmreference re-resolves when the template or parameters changed, asecretsmanagerreference only when its resource changed, as measured on AWS. Contributed by @iot-rocket. - CloudFormation —
DeletionPolicyandUpdateReplacePolicyare honoured — aRetainresource now stays (with aDELETE_SKIPPEDevent) on stack delete, on removal from the template and on replacement;RetainExceptOnCreateandDeleteStack'sRetainResourcesbehave as the API documents;Snapshotdeletes, since the emulator takes no snapshots. Contributed by @iot-rocket.
Fixed
- Lambda — the Docker executor extracts each code and layer zip once — every cold start unpacked the code and layers into a fresh temporary directory that accumulated (a 30 MB function wrote 60 MB of disk per cold start). Extraction is now content-addressed into one shared read-only directory per distinct zip, so a repeat cold start writes nothing; entries are swept when the referencing function or layer version goes, and a state reset clears the cache.
- S3 Tables / Glue — the Iceberg REST catalogs honour
upgrade-format-version— the commit action a Spark job sends for theformat-version3table property was silently dropped, so the table kept reporting version 2; real S3 Tables supports Iceberg v3. Both catalogs now apply it atomically: re-asserting the current version is a no-op, a downgrade or a version above 3 is refused with 400 and commits nothing. - CloudFormation —
Fn::Cidr,Fn::GetAZs,Fn::FindInMapand the condition functions follow AWS —Fn::Cidrnow splits the block it is given (was10.0.{i}.0/…always; IPv6 included),Fn::GetAZsanswers the stack's own zones (was a fabricateda/b/c),Fn::FindInMapgainsDefaultValueand fails a missing key withTemplate error: Unable to get mapping for M::x::y, andFn::And/Fn::Or/Fn::Notin a value position resolve to a boolean — all measured on AWS. Contributed by @iot-rocket. - S3 — the Multi-Region Access Point alias follows the documented pattern — the alias was 13 uuid-hex characters, so a digit-only draw was possible; it now matches S3's
^[a-z][a-z0-9]*[.]mrap$: a letter, then twelve lowercase letters or digits. Contributed by @iot-rocket. - CloudFormation — parameter constraints are enforced —
AllowedPattern,MinLength,MaxLength,MinValueandMaxValuewere ignored; they are checked before a stack exists with CloudFormation's message (Parameter 'P' must match pattern ^[a-z]+$, measured) or theConstraintDescription, per member for aCommaDelimitedList. Contributed by @iot-rocket. - CloudFormation — an unregistered
AWS::CloudFormation::*type is unrecognized, not a silent no-op —Macro,HookVersion,ModuleVersionand any typo under the prefix deployed as a placeholder with a fabricated physical id; the pre-flight now refuses them like every other unrecognized type. Contributed by @iot-rocket. - CloudFormation — the stack id addresses
GetTemplateSummaryand an UPDATE change set — both looked the id up by name and answered "does not exist" while every other action accepted it;DescribeStackResource(s)also answered a request by id with the id inStackName. Contributed by @iot-rocket. - CloudFormation — a change set sees
DeletionPolicy,UpdateReplacePolicyandMetadataedits — the diff comparedPropertiesonly, so a CDKremovalPolicyedit endedFAILEDwith "didn't contain changes"; those attributes now count as aModifywithReplacement: False, reported inScopeandDetails, while aDependsOn-only edit stays a no-change set, as on AWS. Contributed by @iot-rocket. - CloudFormation — a leftover whose delete failed stays visible, and the resource record serves
ResourceStatusReason,MetadataandLastUpdatedTimestamp— a resource dropped from the template whose cleanup delete failed vanished from the record while it kept existing, andDeleteStacknever retried; it now stays listed asDELETE_FAILEDwith its reason, the next update andDeleteStackretry it.DescribeStackResource(s)carryResourceStatusReason; the detail names its timestampLastUpdatedTimestampasStackResourceDetaildefines (clients dropped theTimestampelement it sent) and returns the resourceMetadatawith intrinsics interpreted. Contributed by @iot-rocket.