What it is
Of the four platform records that bracket an invocation, this is the only one with nothing corresponding to it in the text log format. Text logging gives you START, END and REPORT. JSON logging gives you platform.start, platform.runtimeDone and platform.report — and runtimeDone carries information the text format simply never had.
The valuable part is status. It is the runtime's own report of how the invocation ended, written by the platform rather than derived from anything your code printed. Determining whether an invocation failed from text logs means scanning for exception patterns, stack traces, or the phrase "Task timed out" — heuristics that work well until a message is truncated, a stack trace is interleaved with another execution's output, or the function fails without logging anything at all. This field is none of those things. It is an assertion.
producedBytes is the quieter field and worth watching. It measures the response your handler returned, and Lambda caps a synchronous response at 6 MB. An endpoint whose response grows with the data behind it — a list with no pagination, an export that gets larger every month — will cross that limit eventually, and this field is where the approach is visible beforehand. Watching it climb across invocations is considerably cheaper than discovering the ceiling when your largest customer does.
There is one diagnostic worth knowing that comes from this record being absent. It is emitted when the runtime finishes normally. A process killed by the out-of-memory killer never gets there — the kernel removes it between instructions — so the invocation produces a platform.report with no platform.runtimeDone before it. That asymmetry is one of the clearest available signals that a function was killed rather than that it failed, and it is only visible if you are looking at the records of one invocation together rather than scrolling a merged stream.
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
5 raw lines, in the order CloudWatch delivered them.
LogStitch After
The same lines, grouped into the invocation they belong to.
Successc39e5a72-1d64-4f80-a123-7e4c9b1d5f62
- 11:22:44.102PLAT
START RequestId: c39e5a72-1d64-4f80-a123-7e4c9b1d5f62 Version: $LATEST
- 11:22:44.108
Building monthly export
- 11:22:45.902
Assembled 18402 rows
- 11:22:45.944PLAT
RUNTIME_DONE RequestId: c39e5a72-1d64-4f80-a123-7e4c9b1d5f62 Status: success Duration: 1842.07 ms
- 11:22:45.948PLAT
REPORT RequestId: c39e5a72-1d64-4f80-a123-7e4c9b1d5f62 Duration: 1842.07 ms Billed Duration: 1843 ms Memory Size: 1024 MB Max Memory Used: 412 MB
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.
| Field | Type | Meaning |
|---|---|---|
| requestId | string | The invocation this completion belongs to, matching its platform.start. |
| status | string | The runtime's verdict — success, failure, or timeout. This is written by the platform rather than inferred from log text, which makes it the most authoritative status signal in the log. |
| metrics.durationMs | number | How long the runtime spent on the invocation. Compare it against the duration on platform.report to see what accounting added. |
| metrics.producedBytes | number | The size of the response the handler returned. Useful for spotting a payload creeping toward Lambda's 6 MB response limit before it crosses it. |
When it appears
Once per invocation, between the function's last output and its platform.report. It is emitted when the runtime finishes with the request — after your handler returns or throws, and before Lambda has finished accounting for the execution.
Its position is what makes it useful. The gap between platform.runtimeDone and platform.report is post-processing the runtime does after your code is finished, so a response that takes a long time to serialise or a large payload to transmit shows up as separation between these two timestamps rather than in your handler's own duration.
It is also the record most often missing when something is genuinely wrong. An invocation killed by the out-of-memory killer never reaches it, because the process no longer exists — so a request ID with a platform.report and no platform.runtimeDone is a strong signal that the runtime died rather than returned.
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.
Related errors
Errors that show up alongside this one, or that people mistake for it.
References
- AWS Lambda Developer Guide — Lambda Telemetry API Event schema reference
- AWS Lambda Developer Guide — Configuring advanced logging controls
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.