Overcast is alpha — behaviour and APIs may change between releases. Pin your version and read the changelog before upgrading.

overcast

CloudFormation limitations

Every CloudFormation divergence from AWS in one table, which state each operation may start from, and the resource types a stack waits on before completing.

Every divergence from AWS behind CloudFormation, which state each operation may start from, and the resources a stack waits on.

Divergences

AreaOvercastDetail
AWS::NoValueSubstitutes the empty string rather than removing the property
{{resolve:s3:…}}Not resolved; fails the resourceDynamic references
SSM dynamic-reference versionsAn explicit version resolves to the current value, with a warningDynamic references
ssm-secure outside the properties AWS allowsFails the resource; AWS refuses the template at CreateStack insteadDynamic references
DeleteStack’s RetainResourcesNot implemented — a resource that keeps refusing cannot be skipped pastTeardown
DeletionPolicy: SnapshotTreated as Retain; no snapshot is ever takenTeardown
Property-hash trackingA stack created before it has no hashes, so its first update treats those resources as unchangedStack updates
Drift detection, StackSets, stack policies, resource importsNot implemented
Unknown resource typesAccepted with a synthetic stub ID, a warning, and an Overcast:-prefixed ResourceStatusReason, rather than rejectedBelow
Metric-math, extended-statistic and anomaly-detection AWS::CloudWatch::AlarmCreated, and says on its status reason that it will not be evaluatedBelow
ClientRequestTokenDefaults to the request ID of the API call, which keys the debug traceBelow
A persistence flush that misses its deadlineLogged; the stack keeps the terminal status it reachedBelow

Which state an operation may start from

The status is enforced, not merely reported.

OperationAllowed fromRefused with
Create (CreateStack, or a CREATE change set at either step)No stack of that name, or a DELETE_COMPLETE tombstoneAlreadyExistsException
Update (UpdateStack, or an UPDATE change set)CREATE_COMPLETE, UPDATE_COMPLETE, UPDATE_ROLLBACK_COMPLETE, IMPORT_COMPLETE, IMPORT_ROLLBACK_COMPLETEValidationError: Stack:<arn> is in <status> state and can not be updated.
Update with DisableRollbackAlso CREATE_FAILED and UPDATE_FAILEDas above, without the option
ContinueUpdateRollbackUPDATE_ROLLBACK_FAILEDas above
RollbackStackCREATE_FAILED, UPDATE_FAILED, UPDATE_ROLLBACK_FAILEDas above

A change set’s own REVIEW_IN_PROGRESS placeholder is the one exception to the create rule, and only for change sets: CreateStack against that placeholder still fails, as on AWS. ROLLBACK_COMPLETE has no last known stable state, so it is delete-only — which is why the CDK CLI deletes such a stack before deploying it again. A change set may be created against CREATE_FAILED/UPDATE_FAILED without DisableRollback, because that option belongs to the execution.

Resources that wait

Some services answer a create long before the thing they created is usable, and CloudFormation does not pass that on: the resource is not CREATE_COMPLETE until it settles, and anything downstream waits behind it.

Resource typeComplete when
AWS::RDS::DBInstance / DBClusterit reports available
AWS::ElastiCache::CacheCluster / ReplicationGroup / ServerlessCacheit reports available
AWS::EFS::FileSystem / MountTarget / AccessPointit reports available
AWS::MSK::Clusterthe cluster reports ACTIVE
AWS::EKS::Clusterthe cluster reports ACTIVE
AWS::Lambda::Functionthe function reports Active
AWS::ECS::Serviceone deployment left, running its desired count, with rolloutState: COMPLETED where the controller reports one

Status matching folds case, because AWS does not spell one service’s vocabulary consistently. An unrecognised status keeps the resource waiting rather than completing it: AWS adds statuses, and completing on one nothing here understands is the failure these waits exist to prevent. Which statuses end a wait comes from AWS’s own machine-readable answer wherever it has one — the waiters botocore ships.

Updates wait on the same condition, so an UPDATE_COMPLETE means the change was applied and settled. A resource that cannot settle fails with the reason the service itself gives — an RDS event, the newest actionable ECS service event, an MSK stateInfo, an EKS health issue, a Lambda StateReason — and the stack rolls back. A failed update is never answered by replacing the resource; the change has already been applied to the one that exists.

A Lambda function is complete at Active, which is what real CloudFormation waits for. Active means deployed, not working: a function with a broken handler is Active on AWS too and fails at invoke, so the wait stops there.

Every wait runs whether or not the deployment has a container runtime behind the service. A resource with no container coming reaches its ready status as soon as it is recorded, and the wait gets its answer on the first poll.

Stacks are addressable by name or ARN — a deleted stack only by ARN

Every stack-scoped operation’s StackName accepts either the name or the unique stack ID while the stack is live, exactly as AWS documents. A stack’s name becomes reusable the moment it reaches DELETE_COMPLETE, so from then on a name-based read answers ValidationError: Stack with id <name> does not exist — the same answer a name that was never created gets — while the ARN, which embeds the generation’s uuid, still resolves the deleted stack’s final state and events. CDK’s deploy monitor relies on that, and the AWS SDK’s stack-delete-complete waiter treats that ValidationError as the terminal success case.

HandleOn a DELETE_COMPLETE stack
Name, read operationValidationError — the name is reusable
ARN, read operationResolves the deleted generation’s final state and events
Either handle, UpdateStack or CreateChangeSetReports the stack does not exist
Either handle, DeleteStackA no-op success
A stale ARN from a deleted-and-recreated stack of the same nameResolves to nothing; stacks are keyed by name

A stack mid-DELETE_IN_PROGRESS still resolves by name; only the completed record excludes it.

A limitation a resource carries is its ResourceStatusReason

A resource Overcast creates but will not act on in full is provisioned, and the shortfall rides its status reason on the CREATE_COMPLETE/UPDATE_COMPLETE event, so a deploy shows it as the resource goes by rather than only on a later describe. Refusing such a resource instead would fail the stack over something the template is right to contain. AWS::CloudWatch::Alarm is the current case: a metric-math, extended-statistic or anomaly-detection alarm is created and says it will not be evaluated. The same channel carries the stub and inert-tier notice described on the landing page.

Nothing here enters StackStatusReason or changes the stack’s own status — the signal is per-resource, and DescribeStackEvents is what a cdk deploy actually polls.

A persistence flush is not a stack failure

After a stack reaches a terminal status its state is flushed to the persistent store, so a restart straight afterwards still finds it. A flush that does not finish in time is logged and nothing more — the stack keeps the status it reached. Every resource in it exists and answers requests, and the queued writes are neither lost nor abandoned: they go back at the head of the pending queue, and the pending log replays them after an unclean exit. Whether the store is keeping up is reported by /_overcast/health and /_overcast/debug/metrics.