DocsAWS 101Blog
← Back to Blog

v1.3.16 — Warm-boot persistence sweep, wire-format fixes, and Lambda S3ObjectVersion

April 27, 2026 · v1.3.16

1.3.16 is a hardening release. Twelve account-scoped state dicts that were silently disappearing on warm-boot are now persisted, ten list endpoints stop returning NextToken: null (which Java and Go pagination clients would loop on), Lambda Code.S3ObjectVersion is threaded end-to-end so versioned deploys actually pin the right bytes, and SNS→SQS raw delivery finally ships MD5OfMessageAttributes so JVM receivers stop rejecting the digest.

1. Twelve state dicts that were silently dropped on warm-boot

PERSIST_STATE=1 is the knob that makes MiniStack survive a container restart. The contract is simple: every service module exposes get_state() and restore_state(), and the persistence layer round-trips them through JSON.

The contract was incomplete. Twelve module-level AccountScopedDicts were being mutated by public APIs but missing from one or both halves of the persistence path. Most landed in 1.3.16:

There was also a subtler bug in SQS _queue_name_to_url: the dict was snapshotted via dict(asd) instead of copy.deepcopy(asd). AccountScopedDict.__iter__ only yields the current request's keys, so multi-tenant deployments lost every other tenant's queue-name mappings on shutdown serialisation.

Big thanks to @bognari for pushing through most of this audit.

2. Wire-format alignment with the JVM and Go SDKs

A class of bugs easy to miss in Python-only testing: AWS SDKs differ in how they handle null and PascalCase. boto3 strips nulls client-side and is forgiving about case; Java SDK v2 and Go SDK v2 are stricter.

3. Lambda Code.S3ObjectVersion threaded end-to-end

Before 1.3.16, Code.S3ObjectVersion was accepted by CreateFunction / UpdateFunctionCode / PublishLayerVersion and the CloudFormation AWS::Lambda::Function provisioner — but the version was dropped before it reached the S3 fetcher, so deploys silently picked up the latest object version regardless of what was pinned. Terraform aws_lambda_function.s3_object_version and CDK Code.fromBucket(..., objectVersion=...) users got "works on first apply, mysteriously different bytes on the next" for any function whose S3 object had multiple versions.

1.3.16 threads the version through every entry point so the pinned bytes actually deploy:

resource "aws_s3_object" "lambda_zip" {
  bucket = aws_s3_bucket.deploy.id
  key    = "fn.zip"
  source = "build/fn.zip"
  etag   = filemd5("build/fn.zip")
}

resource "aws_lambda_function" "fn" {
  function_name     = "my-fn"
  role              = aws_iam_role.fn.arn
  handler           = "index.handler"
  runtime           = "python3.12"
  s3_bucket         = aws_s3_object.lambda_zip.bucket
  s3_key            = aws_s3_object.lambda_zip.key
  s3_object_version = aws_s3_object.lambda_zip.version_id
}

Also in this release

Upgrade

# Docker
docker pull ministackorg/ministack:1.3.16

# pip
pip install -U ministack

Full changelog: CHANGELOG.md.

Shipped by the MiniStack community. Contributions credited throughout. GitHub · r/ministack