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

overcast

Lambda limitations

Where Overcast's Lambda diverges from AWS, in one table, with the page carrying the detail behind each row: concurrency, execution environments, event delivery, logging and runtimes.

Every divergence from AWS behind Lambda, and the page that carries the detail.

Divergences

AreaDivergenceDetail
Async invocationRetries, destinations and DLQ all work; only the exhausted-concurrency retry-to-queue case differs from AWSEvent delivery
Partial batch responsesReportBatchItemFailures is honoured; an unreadable response fails the whole batchEvent delivery
Concurrency quotasAccount-wide quotas and requests-per-second limits are not emulated; only reserved concurrency is enforcedConcurrency
Cold-start latencyNot simulatedExecution environments
Runtime environment validationMinimalRuntimes
Extension telemetry (Logs API / Telemetry API)HTTP destinations onlyLogging
SnapStartNot emulated — no restore records; platform.runtimeDone reports only responseLatencyLogging
LoggingConfig: {} (explicitly empty)UpdateFunctionConfiguration returns 501Logging
TracingConfig / EphemeralStorage / KMSKeyArnStored and returned, never enforcedBelow
Resource policiesEvaluated for service-originated invokes only, and only under a knob; PutResourcePolicy always refuses a public policyBelow
Update statusEvery update but an image UpdateFunctionCode answers Successful rather than InProgressBelow
Unqualified DeleteFunctionRemoves the function record; versions, aliases and version counters are left behindBelow
TaggingFunctions and event source mappings only; other taggable resources return 501Below
Pinned Code.S3ObjectVersionExcluded from the reactive S3 code syncBelow
Reactive S3 code syncOnly moves a function onto bytes it is not already runningBelow
VPC placementNot restricted on a native Windows or macOS hostBelow

Recorded but not honoured

TracingConfig, EphemeralStorage and KMSKeyArn are validated against AWS’s own constraints, stored, and returned by GetFunction, GetFunctionConfiguration, CreateFunction and UpdateFunctionConfiguration, so a template or SDK client reads back exactly what it set. None of them changes what the function does.

SettingWhat it does not do
TracingConfigNo segment is recorded and no trace exists, whichever Mode is set; Active and PassThrough behave identically
EphemeralStorageThe size is not enforced — a function configured with 512 MB of /tmp gets whatever the Docker host gives it, normally far more
KMSKeyArnAn association only; environment variables are stored in plaintext, as all Overcast state is

Update status

AWS answers every update LastUpdateStatus: InProgress and settles a moment later. Overcast answers Successful: a zip deployment and every UpdateFunctionConfiguration are durably applied before the call returns, so aws lambda wait function-updated returns on its first poll. The one update that really is asynchronous — UpdateFunctionCode pointing a PackageType=Image function at a new image — answers InProgress and settles to Successful, or Failed with ImageAccessDenied/InvalidImage/InternalError, when the pull does.

Resource policies

AddPermission and PutResourcePolicy always store and validate what they are given. Whether a statement then decides anything is a switch: OVERCAST_ENFORCE_LAMBDA_RESOURCE_POLICY, off by default.

Turned on, it gates the invocations Overcast originates on another service’s behalf — S3 bucket notifications, SNS subscription deliveries, API Gateway integrations and EventBridge rule targets — against the target’s policy, and each caller fails the way AWS does: S3 refuses the notification configuration with InvalidArgument, SNS dead-letters the delivery, API Gateway answers 500, and EventBridge records a failed invocation. A direct Invoke is never gated in either setting: Overcast accepts credentials without validating them, so there is no caller identity to authorise.

Three things the evaluation does not do. A condition key it cannot evaluate — anything but aws:SourceArn and aws:SourceAccount — refuses the statement rather than ignoring the condition. A policy is read at the qualifier being invoked, so a Resource ending :* written against the unqualified function does not reach its own aliases. And EventBridge Scheduler is not gated at all, because AWS grants it through an execution role instead.

The reactive S3 code sync

An unpinned function is moved onto new bytes when a new object lands at its S3Bucket/S3Key. Two limits apply:

  • A function whose code names a Code.S3ObjectVersion is pinned to that version and excluded from the sync, which matches AWS. Use UpdateFunctionCode to move it.
  • The sync only moves a function onto bytes it is not already running. A PutObject re-uploading an unchanged asset, or one landing just before a CreateFunction reads the same key, is not a new deployment: RevisionId and LastModified stay put and the warm environment survives.

Deleting a version, and where tags live

DeleteFunction means two different things depending on whether you pass a qualifier — either as ?Qualifier= or inside the function name (my-function:2):

RequestEffect
DELETE /functions/my-functionDeletes the function, its package and its resource policies
DELETE /functions/my-function?Qualifier=2Deletes only published version 2, its qualified policy and its provisioned concurrency
?Qualifier=$LATEST400 InvalidParameterValueException$LATEST only goes with the function
Qualifier naming a version an alias points at409 ResourceConflictException naming the aliases
Qualifier naming an alias409 ResourceConflictExceptionDeleteFunction never deletes an alias
Qualifier naming neither404 ResourceNotFoundException

A qualified delete never touches $LATEST, the function record, other versions, aliases or unqualified policies, and it does not rewind the version counter — AWS never reuses a version number.

Tags attach to the unqualified function ARN, never to a version or alias, so TagResource, UntagResource and ListTags reject a qualified ARN with InvalidParameterValueException. They take an ARN, not a bare function name. Event source mappings are taggable through the same three operations, and CreateEventSourceMapping accepts a Tags map, as CloudFormation sends on every deploy carrying stack tags. Their tags are stored separately and never appear in EventSourceMappingConfiguration, so ListTags is the only way to read them back. Code signing configurations, capacity providers and network connectors return 501 from the tag operations.

VPC placement — VpcConfig

A function with a VpcConfig naming subnets is placed on that VPC’s network and nothing else. It can reach what is in the VPC with it and cannot reach a container outside it, matching AWS, where placement subtracts rather than adds.

Important

On a native Windows or macOS host the restriction is not applied. It needs Overcast’s DNS resolver, and that needs an /etc/resolv.conf those hosts do not have. There the function joins its VPC network and the shared data plane and reaches everything on both, so a test of your VPC wiring passes whether or not the wiring is correct. Run Overcast in a container to get the restriction. See Networking § The Docker networks Overcast uses.

Overcast’s own API endpoint is the exception and stays reachable from every function regardless of placement. AWS_ENDPOINT_URL and the Lambda Runtime API ride a separate control plane, so calling S3 or DynamoDB from inside a VPC works here without the NAT gateway or VPC endpoint AWS would need.

A database in a VPC with the function outside it never worked on AWS either. Put the function in the VPC, or set PubliclyAccessible on the instance; the refused connection is named rather than left to hang.