# Investigate Lambda Timeouts in a Serverless Service

Yes. An agent reads your Serverless Framework service and recent commits and writes an incident report ranking each Lambda timeout suspect with file:line evidence.

[Run this on Rush](https://cloud.getrush.ai/run/investigate-lambda-timeouts/serverless/), in a Project that has your repository.

## What the agent does

The agent clones the repository into its own cloud sandbox and reads the service the incident names. In a service like `aws-node-rest-api-with-dynamodb` from serverless/examples, it reads `serverless.yml` first: `frameworkVersion: '4'`, `runtime: nodejs24.x` on `arm64`, five functions behind `httpApi` routes, and a `TodosDynamoDbTable` with `BillingMode: PAY_PER_REQUEST` and only a hash key on `id`. It notes what the file does not set: there is no `timeout` and no `memorySize` on the provider or on `list`, so the function runs with the framework's defaults, and a default timeout of 6 seconds matches the 6 s in the incident exactly.

Then it reads the handler. `todos/list.js` creates a `DynamoDBDocumentClient` once at module scope and runs a single `ScanCommand({ TableName: process.env.DYNAMODB_TABLE })` with no `Limit`, no `ProjectionExpression` and no loop over `LastEvaluatedKey`, then returns `JSON.stringify(result.Items)`. The agent records two suspects from those lines. A scan reads every item it passes over, so consumed read capacity grows with the table, which matches the spike in the prompt. And one `Scan` call returns at most 1 MB, so on a table past a million items the endpoint also returns an incomplete list, a second bug the timeout hides.

It checks the rest of the path for anything that adds time: the IAM statement grants `dynamodb:Scan` and `dynamodb:Query` on the table, the `package.json` dependencies are `@aws-sdk/client-dynamodb` and `@aws-sdk/lib-dynamodb` at `^3.700.0`, and the other handlers use `GetItem`, `PutItem`, `UpdateItem` and `DeleteItem` on the key. Then it reads the 30 most recent commits with `git log` and `git show`, looking for changes to `serverless.yml`, to the handler, to the table definition or to the SDK version.

For each suspect it writes the check that confirms or clears it, using the data on-call already has: the function's `Duration` and `Max Memory Used` in the CloudWatch `REPORT` lines, `ConsumedReadCapacityUnits` on the table, the item count and table size, and a Datadog query over the same window if the prompt names one. It changes no code and deploys nothing.

## Start it with one API call

`POST https://api.prix.dev/o/{org}/sessions`

```json
{
  "agent": "claude",
  "input": "Incident: Datadog shows the list function in aws-node-rest-api-with-dynamodb timing out at 6 s on 12% of invocations and DynamoDB consumed read capacity spiking, after the table grew past a million items. Read serverless.yml, the handlers, package.json and the last 30 commits, find the most likely causes, and write incident.md with a timeline, each suspect with file and line evidence, and the check that would confirm or clear it, including which framework defaults apply because serverless.yml does not set them. Change no code and deploy nothing.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    }
  ]
}
```

1. **Get an API key.** In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
2. **Send the request.** POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
3. **Read what came back.** Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

## What comes back

What comes back is `incident.md` as an artifact on the session, with a download link the session read returns. It opens with a timeline from the commits and the facts in the prompt, then ranks the suspects. For a list endpoint like this one that means the unbounded `ScanCommand` in `todos/list.js` line 7, the missing `timeout` and `memorySize` in `serverless.yml`, and the missing pagination over `LastEvaluatedKey`, each with the quoted line, how it produces the symptom, and the CloudWatch or DynamoDB metric that confirms it.

The report also says what a fix would look like, without making it: a `Query` on a key or index instead of a scan, pagination with a limit the API returns to the caller, and a timeout and memory size set on purpose. It keeps those as options for a person to choose, because changing the key schema of a table with a million items is a migration, not a one-line change. The session's transcript keeps every file the agent read and every command it ran.

Before acting, the on-call engineer checks the `REPORT` lines and the table's consumed capacity for the incident window against the ranking. If they agree, a follow-up message to the same session can ask the agent to make the change on a branch and open a pull request.

## Run it on every Datadog monitor on Lambda timeouts

A Datadog monitor on a function's error or duration metric can notify a webhook when it triggers. A handler on your server turns that notification into this request, with the function name, the threshold and the time window in the prompt.

Set a webhook URL on the API key and Rush POSTs `run.completed` when the report is ready, with the `session_url`. The handler takes `incident.md` from the session's artifacts and attaches it to the alert, so whoever is paged opens a ranked list of causes instead of a blank page.

## Why run it on Rush?

Serverless repositories often hold many small services, and the cause of a timeout can be in YAML, in a handler or in a default nobody wrote down. Reading them during an incident means cloning, installing and cross-checking framework defaults on a laptop that is also running the AWS console. In a Rush sandbox the agent does the reading and the `git log` work on its own disk, and nothing reaches your AWS account.

The report is cited line by line and each suspect comes with the metric that settles it, so the engineer spends time confirming rather than searching. When several functions alert at once, each one can get its own run in parallel, up to the key's concurrent run limit.

## Frequently asked questions

### Does the agent need my AWS credentials?

No. It reads the repository and writes the checks to run against CloudWatch and DynamoDB. If you want it to read Datadog directly, connect the Datadog MCP server and name it on the run.

### Will it deploy or change the function?

No. The prompt says to change no code and deploy nothing. The result is a Markdown report you download from the session.

### How does it know the default timeout?

It reads `serverless.yml` and notes that neither the provider nor the function sets `timeout` or `memorySize`, so the framework defaults apply. The report says which defaults it assumed so you can check them against the deployed function's configuration.

### My repository has many services. Will it read all of them?

It reads the service the prompt names and anything that service imports or shares. Name the directory in the prompt, as the example does with `aws-node-rest-api-with-dynamodb`, so it does not spend the run on unrelated services.
