Lambda's Execution Model for SDK Callers
Lambda hides servers, but it does not hide its execution model - and that model decides what your SDK calls can and cannot do.
Search across all documentation pages
Lambda hides servers, but it does not hide its execution model - and that model decides what your SDK calls can and cannot do.
When you manage Lambda from boto3 or AWS SDK v3, you are not running code on a box you own. You are asking a managed service to create environments, run your handler inside them, and tear them down. This page explains that model so the API calls in the rest of this section make sense: why cold starts happen, what concurrency really counts, and why "invoke" and "update the function" are two very different kinds of call.
Three ideas explain almost everything an SDK caller sees.
Execution environments run your code. Lambda does not keep your handler resident. When an invoke arrives and no free environment exists, Lambda creates one: it downloads your deployment package or container image, starts the runtime, and runs any initialization code outside the handler. Only then does your handler execute. That build-up is the cold start. Once the invoke finishes, the environment is kept warm for a while and reused by later invokes, which skip the setup entirely.
Concurrency is environments running at once. If ten invokes arrive simultaneously and each takes a second, Lambda runs up to ten environments in parallel - that is a concurrency of ten. Your account has a regional concurrency limit shared across all functions (1,000 by default, raisable). You can carve out a guaranteed slice for one function with reserved concurrency, or pre-warm a fixed number of environments with provisioned concurrency.
The control plane and data plane are separate. Creating a function, changing its memory, publishing a version, or attaching a layer are control-plane operations. Actually running the function is a data-plane operation - Invoke. They scale and behave differently: the data plane is built for very high request rates, while the control plane is for management and is rate-limited and eventually consistent.
"Managing a function via SDK" almost always means one of two things: changing what the function is, or running it.
Changing it uses operations like UpdateFunctionCode, UpdateFunctionConfiguration, PublishVersion, PublishLayerVersion, CreateAlias, and PutProvisionedConcurrencyConfig. Running it uses exactly one operation - Invoke - whose behavior depends on InvocationType.
# --- Python (boto3) ---
import boto3, json
lam = boto3.client("lambda")
resp = lam.invoke(
FunctionName="my-func",
InvocationType="RequestResponse", # wait for and return the result
Payload=json.dumps({"hello": "world"}).encode(),
)
print(resp["StatusCode"], resp["Payload"].read().decode())// --- TypeScript (AWS SDK v3) ---
import { LambdaClient, InvokeCommand } from "@aws-sdk/client-lambda";
const lam = new LambdaClient({});
const resp = await lam.send(new InvokeCommand({
FunctionName: "my-func",
InvocationType: "RequestResponse", // wait for and return the result
Payload: new TextEncoder().encode(JSON.stringify({ hello: "world" })),
}));
console.log(resp.StatusCode, new TextDecoder().decode(resp.Payload));The InvocationType is the pivot. RequestResponse (synchronous) holds the connection open, runs the function, and returns its result and status - so a cold start on that path directly adds to your caller's latency. Event (asynchronous) hands the payload to an internal queue and returns 202 immediately; Lambda drains the queue, retries failures on its own, and can route failures to a dead-letter or on-failure destination. DryRun validates permissions and parameters without running anything.
These pieces interact. A synchronous invoke that hits a cold start pays the setup latency inline, which is exactly why provisioned concurrency exists. An asynchronous invoke absorbs cold starts more gracefully because nobody is waiting on the response. And every concurrent invoke needs its own environment, so a spike in traffic means a spike in cold starts unless enough warm environments already exist.
For an SDK caller, the model turns into a few operational realities.
UpdateFunctionConfiguration or UpdateFunctionCode, the function briefly enters a Pending state (LastUpdateStatus: InProgress). Invoking or updating again immediately can fail with ResourceConflictException. Poll GetFunctionConfiguration or use a waiter until it is Active / Successful before the next step.FunctionError set). Asynchronous failures are retried by Lambda (twice by default) and then dropped or sent to a destination - your caller never sees them directly.The rest of this section is built on these mechanics: you will publish versions and shift traffic between them, pre-warm environments with provisioned concurrency, wire queue and stream triggers, and expose functions over HTTP - all through control-plane and data-plane calls.
Invoke is high-throughput data plane; UpdateFunctionConfiguration is rate-limited, eventually consistent control plane.202 means Lambda accepted it for later execution. There is no result by design; check destinations or logs for the outcome.It is the one-time work Lambda does to create a new execution environment - fetching your code, starting the runtime, and running initialization - before your handler runs. Reused warm environments skip it.
Not directly, but it lets you reduce them: publish a version and set provisioned concurrency on it, trim your package size, and raise memory. Those are all control-plane SDK calls covered in this section.
RequestResponse runs the function and returns its result synchronously, so you wait. Event queues the payload and returns 202 immediately; Lambda runs it later and retries failures itself.
You changed the function while a previous change was still applying. Config updates are eventually consistent - wait until LastUpdateStatus is Successful (or use a waiter) before the next control-plane call.
Both. There is a regional per-account limit shared by all functions, and you can optionally reserve or provision concurrency per function within that limit.
No. Invoke is the data plane, built for high request rates. Create, update, publish, and configure operations are the control plane, which is rate-limited and eventually consistent.
No. You manage the function's definition and its invocations. Provisioning, patching, and scaling of the underlying compute are handled by Lambda.
The next article walks through updating code and config and invoking synchronously versus asynchronously with runnable examples in both SDKs. This page is the model behind them.
Stack versions: This page was written for boto3 1.43.x (Python 3.10+) and the AWS SDK for JavaScript v3 (Node.js 18+).
Reviewed by Chris St. John·Last updated Jul 23, 2026