platform.initStart

Short answer

platform.initStart is the JSON form of the INIT_START line. It marks a new execution environment being built, before any request has been assigned to it, and its initializationType field tells you whether you are paying for a cold start or being served by provisioned concurrency.

What it is

A cold start is not a slow invocation — it is work that happens before any invocation. Lambda creates a container, loads the runtime, imports your module and runs everything at module scope, and only then hands it a request. platform.initStart is written at the beginning of that sequence, which is why it is the one platform record with no request ID: at the moment it is emitted, there is no request.

That has a practical consequence for reading logs. Every other record can be grouped by requestId. This one can only be attributed by position — it belongs to the next invocation to start on that execution environment. On a quiet function that inference is safe. In a log group where several environments are being built at once during a scale-up, several initStart records and several start records interleave, and matching them by eye is guesswork. The reliable cold-start signal in that situation is initDurationMs on the invocation's own platform.report, which needs no inference at all.

initializationType is the field most worth reading, because it answers a question that costs money. on-demand means a real cold start: a user waited for it. provisioned-concurrency means the environment was pre-warmed and the initialisation latency was paid in advance, off the critical path — the record appears at warm-up time rather than at request time. If you are paying for provisioned concurrency and still seeing on-demand in these records during peak traffic, your provisioned capacity is being exceeded and the overflow is falling through to ordinary cold starts. That is exactly the thing provisioned concurrency was bought to prevent, and this field is where it becomes visible.

runtimeVersion deserves an occasional glance too. AWS updates managed runtimes underneath running functions, and a behaviour change with no deployment on your side often correlates with this value moving. It is one of the few places the log records which build actually executed your code.

What it looks like in your logs

With Advanced Logging Controls set to JSON, this record arrives as an envelope. Here it is raw, and then read the way the text format would have shown it.

CloudWatch Logs Before

6 raw lines, in the order CloudWatch delivered them.

{"time":"2026-09-01T03:11:04.882Z","type":"platform.initStart","record":{"initializationType":"on-demand","phase":"init","runtimeVersion":"python:3.12.v41","runtimeVersionArn":"arn:aws:lambda:us-east-1::runtime:9b1f5a2c"}}
{"time":"2026-09-01T03:11:06.115Z","type":"platform.start","record":{"requestId":"0f3a91cc-4f10-4c11-8f0b-1b2d3e4f5a01","version":"$LATEST"}}
{"time":"2026-09-01T03:11:06.118Z","type":"function","record":"Cold container, importing pandas and boto3"}
{"time":"2026-09-01T03:11:06.402Z","type":"function","record":"Report generated rows=1204"}
{"time":"2026-09-01T03:11:06.404Z","type":"platform.runtimeDone","record":{"requestId":"0f3a91cc-4f10-4c11-8f0b-1b2d3e4f5a01","status":"success","metrics":{"durationMs":290.77,"producedBytes":412}}}
{"time":"2026-09-01T03:11:06.406Z","type":"platform.report","record":{"requestId":"0f3a91cc-4f10-4c11-8f0b-1b2d3e4f5a01","status":"success","metrics":{"durationMs":290.77,"billedDurationMs":291,"memorySizeMB":1024,"maxMemoryUsedMB":388,"initDurationMs":1233.51}}}

LogStitch After

The same lines, grouped into the invocation they belong to.

SuccessCold start · 1.23s init0f3a91cc-4f10-4c11-8f0b-1b2d3e4f5a01dur 291msbilled 291msmem 388/1024MBlogs 6
  1. 03:11:04.882PLAT
    INIT_START Runtime Version: python:3.12.v41
  2. 03:11:06.115PLAT
    START RequestId: 0f3a91cc-4f10-4c11-8f0b-1b2d3e4f5a01 Version: $LATEST
  3. 03:11:06.118
    Cold container, importing pandas and boto3
  4. 03:11:06.402
    Report generated rows=1204
  5. 03:11:06.404PLAT
    RUNTIME_DONE RequestId: 0f3a91cc-4f10-4c11-8f0b-1b2d3e4f5a01	Status: success	Duration: 290.77 ms
  6. 03:11:06.406PLAT
    REPORT RequestId: 0f3a91cc-4f10-4c11-8f0b-1b2d3e4f5a01	Duration: 290.77 ms	Billed Duration: 291 ms	Memory Size: 1024 MB	Max Memory Used: 388 MB	Init Duration: 1233.51 ms
Success
Status
291ms
Duration
291ms
Billed
388/1024MB
Memory
62%
Headroom
Yes
Cold start

The panel on the right is generated by running the excerpt on the left through the same parser that powers the free web stitcher — it is what the tool actually produces for this input, not an illustration of it.

What the record contains

Every field Lambda writes in this record, and what each one is telling you.

FieldTypeMeaning
initializationType string How the environment was created — on-demand for an ordinary cold start, provisioned-concurrency for a pre-warmed one, snap-start where SnapStart is enabled. This is the field that tells you whether the latency was paid by a user.
phase string Which initialisation phase this is, normally init. An invoke phase indicates a re-initialisation after the environment failed and was rebuilt during a request.
runtimeVersion string The exact runtime build, such as nodejs:22.v14. Worth noting when behaviour changes without a deployment — AWS updates these underneath you.
runtimeVersionArn string The full ARN of that runtime version, which is what you pin against if you need reproducible runtime behaviour.

When it appears

Only on a cold start — when Lambda creates a new execution environment rather than reusing a warm one. It appears before the platform.start of whichever invocation ends up being served by that environment, and it carries no request ID, because at the moment it is written no request has been assigned yet.

That missing request ID is the awkward part. Every other platform record can be attributed to an invocation by its requestId; this one has to be attributed by position — it belongs to the next platform.start on the same log stream. In a busy log group with several environments starting at once, that attribution is genuinely ambiguous from the text alone.

With provisioned concurrency the record appears when the environment is pre-warmed, which can be minutes or hours before it serves anything, and initializationType reads provisioned-concurrency rather than on-demand.

Also seen as

The same underlying failure, worded differently by a different runtime, SDK version, or logging layer. All of these land here — there is no separate page for each phrasing.

"type":"platform.initStart"platform.initStart recordINIT_START JSON formatlambda cold start log recordprovisioned-concurrency initializationType

Errors that show up alongside this one, or that people mistake for it.

References

Stop reading JSON envelopes.

LogStitch renders every one of these records as a single readable line, in the invocation it belongs to — the same way the text format shows them, with the raw envelope one toggle away. Paste a log excerpt into the free web stitcher and see it, or run the Mac app against your own AWS profiles.