AWS Lambda 90-Minute Timeout Setup: 12 Steps [2026]

AWS Lambda just tore down a wall that developers had been building workarounds around for a decade. As of September 2026, functions running on AWS Lambda Managed Instances can execute for up to 90 minutes on asynchronous and event source mapping invocations, a 6x jump from the old 15-minute ceiling. If you have ever split a video transcoding job into five chained functions just to dodge a timeout, or bolted on Step Functions purely to babysit a long-running batch task, this changes the calculus. This tutorial walks through setting up, configuring, and hardening a production-ready Lambda function that actually uses the new headroom, from IAM permissions to cost math to the operational traps that catch teams off guard in the first week.

Google · Preferred Sources

Don't miss new tech stories on Google

Add Tech Insider once in the Google app and our stories appear in your news suggestions.

Add Now

What Changed With AWS Lambda Managed Instances

AWS Lambda Managed Instances (LMI) is a Lambda execution mode that runs functions on dedicated, AWS-managed compute instead of the traditional Firecracker microVM-per-invocation model. According to AWS’s official Compute Blog announcement, “AWS Lambda now supports a 90-minute function timeout for asynchronous and event source mapping (ESM) invocations on AWS Lambda Managed Instances (LMI), a capability of AWS Lambda.” That single sentence quietly rewrites what counts as a “serverless” workload.

Before this release, every Lambda invocation topped out at 900 seconds (15 minutes), full stop. Teams running data pipelines, video transcoding, financial batch reconciliation, or long AI inference chains either moved to Fargate, wrote orchestration logic across multiple chained Lambda calls, or gave up on serverless entirely for that workload. AWS confirms the new limit directly in its documentation: “You can now configure any Lambda function running on a Managed Instance with a timeout of up to 90 minutes (5,400 seconds) for async and ESM invocations.” Synchronous invocations, by contrast, keep the familiar 15-minute cap, and the Init phase (cold start initialization) is still bounded at 15 minutes even on Managed Instances.

There’s a second detail that matters for anyone doing capacity planning: AWS states plainly that “there is no additional charge for using the 90-minute timeout.” You pay standard Lambda Managed Instances compute pricing for however long the function actually runs, not a premium surcharge for accessing the longer ceiling. That makes this a pure win for workloads that were previously forced into more expensive or more complex architectures just to survive past the 15-minute mark.

This tutorial assumes you are comfortable with basic AWS console navigation and the AWS CLI. We will build a working long-running Lambda function step by step, wire it into a durable execution pattern, and cover the cost, security, and troubleshooting details that determine whether this setup survives contact with production traffic.

Prerequisites and Versions You Need

Get these lined up before you touch the console. Skipping any one of them is the single most common reason this setup fails on the first attempt.

  • An active AWS account with billing enabled (Lambda Managed Instances is a paid compute tier, not part of the always-free tier)
  • AWS CLI version 2.31 or later – run aws --version to confirm; older CLI builds do not expose the --timeout 5400 parameter range for Managed Instances
  • AWS SAM CLI version 1.150 or later if you plan to deploy via Infrastructure as Code
  • Python 3.13 or Node.js 22.x runtime target (both are current supported Lambda runtimes as of late 2026)
  • IAM permissions to create Lambda functions, IAM roles, SQS queues, and CloudWatch alarms
  • A code editor with AWS Toolkit installed (VS Code or JetBrains both work)
  • Basic familiarity with JSON for IAM policies and SAM templates
  • Roughly 90 minutes of uninterrupted setup time, appropriately enough

One clarification worth flagging up front: Lambda Managed Instances is a distinct execution environment from standard Lambda. Not every account has it enabled by default in every region at launch, so your first practical step is confirming access, which we cover in Step 1 below.

Step 1: Confirm Lambda Managed Instances Access in Your Region

Open the Lambda console and check which regions currently expose the Managed Instances compute option. AWS rolled this out to major commercial regions first (US East, US West, EU West, EU Central, and the main Asia-Pacific regions), with broader coverage following in subsequent weeks. Run this CLI check to see what your account can access:

aws lambda get-account-settings --region us-east-1

# Look for AccountLimit and confirm your account isn't
# capped below the concurrent execution levels you plan to use
aws lambda list-functions --region us-east-1 --max-items 5

If the console shows a “Managed Instances” toggle when creating a new function, you have access. If it does not appear, request access through AWS Support or check the AWS What’s New page for your region’s rollout status. Do not skip this check: attempting to set a 5400-second timeout on a standard (non-Managed Instances) function will simply fail validation, and the error message does not always make the root cause obvious.

Step 2: Create the IAM Execution Role

Every Lambda function needs an execution role. For a long-running function, scope this role tightly, because a 90-minute execution window gives a misconfigured or compromised function far more time to do damage than a 15-minute one ever could.

aws iam create-role \
 --role-name lambda-lmi-long-runner-role \
 --assume-role-policy-document '{
 "Version": "2012-10-17",
 "Statement": [{
 "Effect": "Allow",
 "Principal": {"Service": "lambda.amazonaws.com"},
 "Action": "sts:AssumeRole"
 }]
 }'

aws iam attach-role-policy \
 --role-name lambda-lmi-long-runner-role \
 --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

Add any additional permissions your workload needs (S3 read/write, DynamoDB access, Secrets Manager) as separate, narrowly-scoped policies rather than attaching broad managed policies. This matters more here than on typical short-lived functions because of ephemeral credential expiration, which we cover in the troubleshooting section.

Step 3: Write the Function Code for Long-Running Execution

The function code itself does not need special syntax to run longer, but it should be written to survive a 90-minute execution window gracefully, with progress checkpoints and clean error handling. Here’s a Python example structured for a data processing workload:

import json
import time
import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)

def handler(event, context):
 records = event.get("records", [])
 total = len(records)
 processed = 0

 for i, record in enumerate(records):
 # Check remaining time and checkpoint before the function
 # is forcibly terminated by the platform
 remaining_ms = context.get_remaining_time_in_millis()
 if remaining_ms < 60000:
 logger.warning(
 f"Approaching timeout with {total - processed} records left. "
 f"Persisting checkpoint at record {i}."
 )
 save_checkpoint(i, event.get("job_id"))
 break

 process_record(record)
 processed += 1

 if processed % 500 == 0:
 logger.info(f"Processed {processed}/{total} records")

 return {
 "statusCode": 200,
 "body": json.dumps({"processed": processed, "total": total})
 }

def process_record(record):
 time.sleep(0.05)

def save_checkpoint(index, job_id):
 logger.info(f"Checkpoint saved for job {job_id} at index {index}")

The context.get_remaining_time_in_millis() call is the piece most tutorials skip, and it is the single most useful line in this whole function. It lets your code checkpoint gracefully and hand off to a resumed invocation instead of being killed mid-record with no state saved. On a 90-minute window processing potentially tens of thousands of records, that checkpoint logic is not optional.

Step 4: Configure the 90-Minute Timeout via AWS CLI

Package and deploy your function, then set the extended timeout. This is the core configuration step, and AWS documents the exact command pattern in its Lambda function timeout configuration guide:

# Zip and create the function first
zip function.zip lambda_function.py

aws lambda create-function \
 --function-name my-data-processor \
 --runtime python3.13 \
 --role arn:aws:iam::123456789012:role/lambda-lmi-long-runner-role \
 --handler lambda_function.handler \
 --zip-file fileb://function.zip \
 --timeout 900 \
 --memory-size 2048

# Now update to the extended 90-minute (5400 second) timeout
# This only succeeds on functions running on Managed Instances
aws lambda update-function-configuration \
 --function-name my-data-processor \
 --timeout 5400 \
 --region us-east-1

Note the two-step deploy: you cannot set 5400 seconds at initial creation in every SDK version, so creating with a standard timeout first and then updating is the more reliable path across CLI versions. Confirm the change landed correctly:

aws lambda get-function-configuration \
 --function-name my-data-processor \
 --query "Timeout"

# Expected output: 5400

Step 5: Deploy via Infrastructure as Code Instead (SAM Template)

For anything beyond a quick test, define the function in a SAM template so the timeout, memory, and permissions are version-controlled rather than set imperatively via CLI. This is also the path AWS recommends for repeatable production deployments.

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
 DataProcessorFunction:
 Type: AWS::Serverless::Function
 Properties:
 FunctionName: my-data-processor
 Runtime: python3.13
 Handler: lambda_function.handler
 Timeout: 5400
 MemorySize: 2048
 Environment:
 Variables:
 JOB_TABLE: !Ref CheckpointTable
 Events:
 AsyncTrigger:
 Type: SQS
 Properties:
 Queue: !GetAtt ProcessingQueue.Arn
 BatchSize: 1

 ProcessingQueue:
 Type: AWS::SQS::Queue
 Properties:
 VisibilityTimeout: 32400
 MessageRetentionPeriod: 1209600

 CheckpointTable:
 Type: AWS::DynamoDB::Table
 Properties:
 BillingMode: PAY_PER_REQUEST
 AttributeDefinitions:
 - AttributeName: job_id
 AttributeType: S
 KeySchema:
 - AttributeName: job_id
 KeyType: HASH

Deploy it with sam build && sam deploy --guided. Notice the SQS VisibilityTimeout is set to 32400 seconds, six times the function timeout. That ratio is not arbitrary, and skipping it is Trap 1 in our pitfalls section below.

Step 6: Understand Which Invocation Types Actually Get 90 Minutes

This is where most first attempts go wrong. The 90-minute window is not universal across every way you can trigger a Lambda function. AWS's own documentation is explicit: "For synchronous and event source mapping invocations, both the invocation and the corresponding durable execution are limited to 90 minutes." Meanwhile, asynchronous durable functions get an even longer runway on the orchestration side, though each individual invocation step is still capped.

Invocation TypeMax Timeout (Standard Lambda)Max Timeout (Managed Instances)Typical Trigger
Synchronous15 minutes15 minutes (unchanged)API Gateway, ALB, direct SDK invoke
Asynchronous15 minutes90 minutesS3 events, SNS, EventBridge
Event Source Mapping (ESM)15 minutes90 minutesSQS, Kinesis, DynamoDB Streams
Durable function execution (async)Not applicableUp to 1 year total, 90 min per stepStep Functions Durable, custom orchestration
Init phase (cold start)15 minutes15 minutes (unchanged)Container/runtime bootstrap

AWS confirms the durable execution detail directly: "With today's launch, each asynchronous invocation in a durable function running on a Managed Instance can now execute for up to 90 minutes continuously, while the corresponding durable execution can run for up to 1 year." That one-year figure surprises people, but it refers to the total orchestration lifetime across many chained 90-minute steps, not a single unbroken invocation.

Practically, if your workload is triggered by an API Gateway request expecting an immediate HTTP response, none of this helps you; synchronous invocations are unchanged. Route long jobs through SQS, EventBridge, or S3 event notifications instead, and have the synchronous entry point simply enqueue the job and return a 202 Accepted response immediately.

Step 7: Wire Up SQS as the Async Trigger Correctly

SQS is the most common trigger for long-running Lambda workloads, and it is also where the most damaging misconfiguration happens. The queue's visibility timeout must exceed six times the function timeout, per AWS's own recommended guidance for event source mappings with batch processing and retries. For a 5400-second (90-minute) function, that means a visibility timeout of at least 32400 seconds (9 hours).

aws sqs create-queue \
 --queue-name lambda-lmi-processing-queue \
 --attributes '{
 "VisibilityTimeout": "32400",
 "MessageRetentionPeriod": "1209600",
 "ReceiveMessageWaitTimeSeconds": "20"
 }'

# Attach it as an event source mapping to the function
aws lambda create-event-source-mapping \
 --function-name my-data-processor \
 --event-source-arn arn:aws:sqs:us-east-1:123456789012:lambda-lmi-processing-queue \
 --batch-size 1

Get the visibility timeout ratio wrong and here is what actually happens: SQS re-delivers the message to a second Lambda invocation while the first one is still running, because the queue assumed the message was abandoned. Now you have two invocations processing the same record simultaneously, and if that record triggers a non-idempotent write (a payment, an email send, a database insert without a uniqueness constraint), you get duplicate side effects that are painful to unwind after the fact.

Step 8: Add CloudWatch Monitoring for Long-Running Invocations

Standard Lambda dashboards assume invocations finish in seconds. A function that legitimately runs for 60-plus minutes needs different alerting thresholds, or every long-running job will trip your existing "function taking too long" alarms.

aws cloudwatch put-metric-alarm \
 --alarm-name lambda-lmi-approaching-timeout \
 --namespace AWS/Lambda \
 --metric-name Duration \
 --dimensions Name=FunctionName,Value=my-data-processor \
 --statistic Maximum \
 --period 300 \
 --threshold 4800000 \
 --comparison-operator GreaterThanThreshold \
 --evaluation-periods 1 \
 --alarm-actions arn:aws:sns:us-east-1:123456789012:lambda-alerts

That threshold (4,800,000 milliseconds, or 80 minutes) gives you a 10-minute warning window before a function actually hits the hard 5400-second wall and gets terminated, so your on-call rotation finds out from an alarm rather than from a customer ticket.

Step 9: Run a Verification Test

Before trusting this in production, force a test invocation that deliberately runs long enough to prove the timeout is actually respected, not silently capped back to 15 minutes by a misconfigured deployment.

aws lambda invoke \
 --function-name my-data-processor \
 --invocation-type Event \
 --payload '{"records": [/* large test payload, 20,000+ items */]}' \
 response.json

# Then poll CloudWatch Logs to confirm actual execution duration
aws logs tail /aws/lambda/my-data-processor --follow

A correctly configured deployment for this test should log a REPORT line with a Duration value well past the old 900,000ms (15-minute) ceiling if your workload genuinely needs that long. If the invocation still terminates at 15 minutes despite your update-function-configuration call reporting Timeout: 5400, jump to the troubleshooting section below.

Step 10: Compare This to Fargate and Step Functions for the Same Workload

The 90-minute timeout does not mean Lambda now replaces every long-running compute use case. Here is where it actually competes with, and where it still loses to, the alternatives teams have been reaching for.

ApproachMax DurationCold StartBest Fit
Lambda (standard, 15 min)15 minutes~100-400msShort event handlers, APIs
Lambda Managed Instances (new)90 minutes (async/ESM)~1-3s (dedicated instance)Batch jobs, media processing, mid-length AI inference
AWS FargateUnbounded (task-based)~30-60s container startLong-running services, streaming, always-on containers
Step Functions (Standard)1 year (orchestration)Depends on state tasksComplex multi-step workflows with branching logic

If your job runs 20 to 80 minutes, needs event-driven triggering, and does not need to stay warm indefinitely, Managed Instances now sits in a genuinely useful gap that previously forced a choice between over-engineering with Step Functions or over-provisioning with Fargate. If your workload runs for hours continuously or needs to hold open persistent connections, Fargate remains the better fit; nothing about this release changes that math for AWS ECS, EKS, or Fargate decisions.

Step 11: Calculate Real Cost Before Committing a Workload

Because there's no timeout surcharge, cost on Managed Instances scales with the underlying EC2 instance type (billed at EC2 on-demand rates plus a 15% Lambda management fee) rather than per-GB-second duration, per AWS Lambda's published pricing page. That said, a function running for 60-90 minutes at 2048MB racks up meaningfully more cost per invocation than the sub-minute functions most teams are used to budgeting for.

MemoryDurationApprox. Cost per Invocation1,000 Invocations/Month
1024 MB15 min~$0.015~$15
1024 MB60 minNot GB-second billed on Managed InstancesDepends on EC2 instance type + 15% mgmt fee
2048 MB90 minNot GB-second billed on Managed InstancesDepends on EC2 instance type + 15% mgmt fee
4096 MB90 min~$0.360~$360

These figures are directional estimates based on standard per-GB-second Lambda pricing and will vary by region; always confirm against the AWS Pricing Calculator before committing a workload at volume. The practical lesson is that "no timeout surcharge" does not mean "cheap at scale." A job that used to get force-split across five short Lambda invocations because of the 15-minute wall may now run as a single 90-minute invocation, which is architecturally simpler but is not automatically cheaper. Run the math against your actual batch size before migrating.

Step 12: Harden Ephemeral Credentials for the Longer Window

Lambda's execution role credentials are ephemeral and rotate automatically, but the rotation window was designed around invocations that finish in minutes. On a function running close to 90 minutes, credentials issued at cold start can approach their expiration before the invocation completes, particularly for SDK clients that cache credentials at initialization rather than refreshing per-call.

import boto3
from botocore.config import Config

# Force credential refresh checks rather than caching
# a single client for the full 90-minute execution
def get_fresh_client(service_name):
 session = boto3.Session()
 return session.client(
 service_name,
 config=Config(retries={"max_attempts": 5, "mode": "adaptive"})
 )

Instantiate AWS SDK clients inside the function loop periodically, or at minimum wrap long-running SDK calls in retry logic that catches ExpiredTokenException and re-acquires a client rather than treating it as an unrecoverable error. This is a small code change that prevents a genuinely confusing production failure mode two-thirds of the way through a long batch job.

Common Pitfalls With the 90-Minute Lambda Timeout

Five mistakes account for nearly every failed first attempt at this setup, based on patterns visible across early adopter write-ups and AWS's own documented caveats.

  • Forgetting the SQS visibility timeout ratio. Set it below six times the function timeout and SQS will re-deliver a message to a second concurrent invocation while the first is still mid-flight, causing duplicate processing.
  • Assuming synchronous invocations also get 90 minutes. They do not. API Gateway and ALB-triggered invocations remain capped at 15 minutes regardless of your function's configured timeout value.
  • Ignoring the 350-second NAT Gateway idle connection drop. If your function holds an idle connection through a NAT Gateway (common for VPC-attached functions calling external APIs), the NAT Gateway silently drops connections idle past roughly 350 seconds, well before your 90-minute window ends, causing mysterious mid-execution failures.
  • Not checkpointing progress. A function that fails at minute 85 with no saved state means reprocessing the entire job from scratch. Always persist progress markers to DynamoDB, S3, or an equivalent store.
  • Overlooking that Init phase is still 15 minutes. Loading a large ML model or dataset during cold start can still hit the old ceiling even though your invocation timeout is now 5400 seconds; the Init phase and the invocation phase are governed by separate limits.

Advanced Tips for Production Workloads

Once the basic setup is working, a few refinements separate a demo from something you can trust at scale. First, pair Managed Instances with reserved concurrency limits; a long-running function consuming concurrency slots for up to 90 minutes each can exhaust your account's concurrent execution quota far faster than short functions do, starving unrelated workloads sharing the same account. Second, if your workload is genuinely bursty (occasional 90-minute jobs mixed with high-frequency short ones), split them into separate functions with separate concurrency reservations rather than one function trying to serve both patterns. Third, for AI inference workloads specifically, this timeout increase pairs naturally with Bedrock or SageMaker asynchronous inference endpoints; use Lambda as the orchestration and pre/post-processing layer rather than running the model inference loop directly inside the function, which keeps your Lambda cost predictable and lets the inference service scale independently. Fourth, enable AWS X-Ray tracing on any function using more than 20 minutes of its budget; the added visibility into which internal call is consuming time is worth the marginal tracing cost once executions get this long. Finally, revisit your Lambda function's reserved concurrency and provisioned concurrency settings together; provisioned concurrency reduces cold start latency for the Init phase but does not extend or interact with the 90-minute execution ceiling itself.

Complete Working Project: Long-Running Report Generator

Here is a full, deployable example that ties every step together: an SQS-triggered Lambda function on Managed Instances that generates a large report, checkpoints progress to DynamoDB, and emails completion status via SNS.

import json
import os
import boto3
import logging
from datetime import datetime, timezone

logger = logging.getLogger()
logger.setLevel(logging.INFO)

dynamodb = boto3.resource("dynamodb")
sns = boto3.client("sns")
table = dynamodb.Table(os.environ["JOB_TABLE"])

def handler(event, context):
 for record in event["Records"]:
 body = json.loads(record["body"])
 job_id = body["job_id"]
 dataset_size = body["dataset_size"]

 start_index = get_checkpoint(job_id)
 logger.info(f"Job {job_id} resuming from index {start_index}")

 for i in range(start_index, dataset_size):
 if context.get_remaining_time_in_millis() < 90000:
 save_checkpoint(job_id, i)
 logger.warning(f"Checkpointing job {job_id} at {i}, re-queueing")
 raise TimeoutWarning("Approaching timeout, checkpoint saved")

 generate_report_chunk(i)

 mark_complete(job_id)
 notify_completion(job_id)

 return {"statusCode": 200}

def get_checkpoint(job_id):
 response = table.get_item(Key={"job_id": job_id})
 return response.get("Item", {}).get("last_index", 0)

def save_checkpoint(job_id, index):
 table.put_item(Item={
 "job_id": job_id,
 "last_index": index,
 "updated_at": datetime.now(timezone.utc).isoformat()
 })

def mark_complete(job_id):
 table.update_item(
 Key={"job_id": job_id},
 UpdateExpression="SET #s = :status",
 ExpressionAttributeNames={"#s": "status"},
 ExpressionAttributeValues={":status": "complete"}
 )

def notify_completion(job_id):
 sns.publish(
 TopicArn=os.environ["COMPLETION_TOPIC"],
 Subject="Report Generation Complete",
 Message=f"Job {job_id} finished successfully."
 )

def generate_report_chunk(index):
 pass

class TimeoutWarning(Exception):
 pass

This pattern, checkpoint, raise, requeue via SQS's natural redelivery, resume from checkpoint, is the backbone of nearly every production long-running Lambda workload. Combined with the SAM template from Step 5, this is a complete, deployable project you can adapt to transcoding, ETL, report generation, or batch AI inference immediately.

Expected Output When Everything Works

A successfully configured function produces a CloudWatch log REPORT line resembling this after a long-running invocation completes normally:

REPORT RequestId: 8f3a2c1e-9b7d-4a6f-b2e1-1c9d8e7f6a5b
Duration: 4812034.22 ms
Billed Duration: 4812035 ms
Memory Size: 2048 MB
Max Memory Used: 1877 MB
Init Duration: 612.40 ms

A Duration value above 900,000ms (15 minutes) confirms the extended timeout is active and being respected, not silently truncated. If your function is failing before that threshold with a generic Task timed out error, the configuration did not take effect and you should revisit Step 4.

Troubleshooting Guide

Eight issues account for nearly everything that goes wrong during this setup, drawn from AWS's documented limitations and common early-adopter reports.

  • "Task timed out after 900.00 seconds" despite setting Timeout to 5400. Your function is not actually running on Managed Instances. Check the console's compute type toggle; the extended timeout only applies to that execution mode.
  • Duplicate processing of the same SQS message. Your visibility timeout is too short relative to the function timeout. Set it to at least 6x the function's configured timeout, per AWS's event source mapping guidance.
  • Function dies at exactly 350 seconds despite a 5400-second timeout. A VPC-attached function's NAT Gateway is dropping an idle outbound connection. Add TCP keep-alive settings to your HTTP client or move the resource behind a VPC endpoint instead of routing through NAT.
  • ExpiredTokenException partway through execution. The SDK client cached credentials at cold start and they expired before the 90-minute invocation finished. Re-instantiate clients periodically or upgrade to a current SDK version with automatic credential refresh.
  • CloudFormation deployment rejects Timeout: 5400. Your SAM/CloudFormation template version or the function's compute type is not correctly flagged for Managed Instances. Confirm the resource type and any required compute-type property in the latest AWS::Serverless::Function schema.
  • Function works in testing but times out only under load. Check reserved concurrency; if your account-level concurrent execution limit is being hit, throttled invocations wait and can appear to exceed timeout budgets that were actually fine in isolation.
  • Init phase failing on large model loads. Remember the Init phase remains capped at 15 minutes even on Managed Instances. Move large asset loading (ML models, big config files) to lazy-load inside the handler, or pre-warm via provisioned concurrency.
  • Cost alarms firing unexpectedly after migration. Functions that used to run in 15-minute chunks now legitimately run for 60-90 minutes each. This is expected behavior, not a bug, but update your CloudWatch billing alarms and budget forecasts to reflect the new duration profile before migrating production traffic.

Real-World Use Cases Unlocked by the Longer Timeout

Abstract timeout numbers only mean something once you map them to actual workloads. Video and audio transcoding is the most obvious beneficiary: a 45-minute podcast episode or a mid-length video file can now be transcoded end-to-end in a single Lambda invocation instead of being chunked into segments processed by separate functions and stitched back together afterward. That stitching logic was often more fragile than the transcoding itself, so removing it is a real architectural simplification, not just a convenience.

Financial batch reconciliation is another strong fit. End-of-day reconciliation jobs that compare millions of transaction records against ledger entries routinely ran 20 to 50 minutes on dedicated EC2 instances or Fargate tasks specifically because Lambda could not hold the connection and in-memory state open long enough. Teams can now evaluate moving that job back to Lambda, provided the reconciliation logic tolerates the checkpoint-and-resume pattern shown earlier in this tutorial.

AI inference chains benefit in a more specific way. A single Lambda invocation orchestrating multiple sequential calls to a large language model, running retrieval steps in between, and post-processing the output can now stay within one invocation for chains that previously needed to be split across Step Functions states purely because of the 15-minute ceiling. This does not mean you should run raw model inference inside Lambda itself; keep that on a dedicated inference service and use Lambda for the orchestration and glue logic around it, as noted in the advanced tips section above.

Bulk data migration and ETL jobs round out the common use cases. Nightly jobs that export a large table to S3, transform it, and load it into a data warehouse frequently ran into the 15-minute wall on tables with several million rows. With checkpointing to DynamoDB in place, that same job can now run as a single Managed Instances invocation, re-queueing itself through SQS if it approaches the 90-minute mark on unusually large data sets, rather than requiring a dedicated Glue job or EMR cluster purely for timeout headroom.

Migrating an Existing Chained-Lambda Workflow

If you already have a workload split across multiple chained Lambda functions purely to work around the old 15-minute limit, do not rip it out in one pass. Start by identifying which link in the chain is actually the bottleneck; often only one segment of a five-function chain genuinely needs the extra runway, and the rest were split defensively rather than out of necessity.

Consolidate incrementally. Merge two adjacent functions in the chain into one Managed Instances function with a 30 or 40-minute timeout first, and validate in a staging environment that the checkpoint logic, IAM permissions, and SQS visibility timeout all behave correctly under realistic load before merging further. Watch cold start behavior closely during this phase: Managed Instances cold starts are typically in the 1 to 3-second range rather than the sub-second starts of standard Lambda, since the platform is provisioning dedicated compute rather than reusing a pooled microVM. For latency-sensitive chains, that difference is worth measuring before committing to a full migration.

Keep the old chained version running in parallel behind a feature flag or a separate SQS queue for at least one full production cycle. Long-running batch jobs often only surface edge cases (unusually large records, slow downstream dependencies, throttled API calls) once a week or once a month, so a few days of parallel testing is not enough to catch every failure mode the consolidated version might introduce. Once the consolidated function has run cleanly through a full production cycle, decommission the old chain and remove the now-unnecessary intermediate SQS queues and Step Functions states that existed solely to work around the 15-minute ceiling.

How This Compares to Google Cloud Functions and Azure Functions

AWS is not operating in isolation here. Google Cloud Functions 2nd generation already supports up to 60 minutes of processing time for HTTP functions, along with instance concurrency up to 1,000 concurrent requests per instance, according to Google's own Cloud Functions 2nd generation announcement. Azure, meanwhile, has been pushing its serverless platform toward AI agent workloads specifically, with Microsoft's serverless documentation describing scaling behavior tuned for event-driven and agentic function patterns, per Microsoft's Azure Functions scaling documentation.

The practical takeaway: AWS's 90-minute figure now leads the three major clouds for pure asynchronous execution duration on serverless functions, but each platform is optimizing for a slightly different workload shape. Google's strength remains HTTP-triggered concurrency at scale; Azure is betting heavily on native AI agent orchestration; AWS is extending raw execution duration for batch and event-driven jobs. Pick based on which constraint your actual workload hits first, not on a single headline number.

When You Should Not Use the 90-Minute Timeout

This feature solves a real problem, but it is not a universal upgrade path for every Lambda function you own. If your workload needs to hold a persistent connection open (a WebSocket server, a long-poll listener), Lambda's per-invocation model still is not the right fit regardless of the timeout ceiling; look at Fargate or App Runner instead. If your job genuinely needs more than 90 minutes for a single invocation and cannot be checkpointed, Step Functions Standard workflows or a Fargate task remain the correct choice. And if your workload is latency-sensitive and synchronous (a user is waiting on an HTTP response), none of this helps, because synchronous invocations are unchanged at 15 minutes. Match the tool to the actual trigger pattern and duration profile of your workload rather than defaulting to the newest capability because it is available.

Security Considerations for Long-Running Functions

A function that runs for 90 minutes has a materially larger blast radius than one that runs for 90 seconds if something goes wrong. Review three things before putting a long-running Managed Instances function into production. First, scope the execution role down to exactly the resources the function touches; a broad policy that would have been a minor risk on a short-lived function becomes a much bigger one when an attacker who compromises the function has an hour and a half of active credentials to work with rather than a few seconds. Second, log every external call the function makes, including outbound API requests and downstream service invocations, since a long execution window gives more opportunity for a function to be abused for data exfiltration if it is compromised through a dependency or a malicious input. Third, set a VPC configuration with security groups that restrict outbound traffic to only the specific endpoints the function legitimately needs, rather than allowing broad outbound internet access by default. None of this is unique to Managed Instances specifically, but the extended timeout raises the stakes on getting it right, and it is worth a dedicated review pass rather than assuming your existing short-function security posture transfers unchanged.

Frequently Asked Questions

Does the 90-minute timeout apply to all Lambda functions automatically?
No. It only applies to functions explicitly running on AWS Lambda Managed Instances, and only for asynchronous and event source mapping invocations. Standard Lambda functions and synchronous invocations remain capped at 15 minutes.

Is there an extra fee for using the longer timeout?
No. AWS states there is no additional charge for using the 90-minute timeout itself; you pay standard per-GB-second compute pricing for however long the function actually runs.

Can I set the timeout to something between 15 and 90 minutes, like 45 minutes?
Yes. The 90-minute figure is the maximum, not a fixed value. Set any timeout value up to 5400 seconds that matches your workload's actual needs.

Does this replace the need for AWS Step Functions?
Not entirely. Step Functions still handles complex branching logic, human-in-the-loop approval steps, and orchestration across many services better than a single Lambda function can. Durable functions on Managed Instances can run for up to a year in total orchestration time, but that is chained 90-minute steps, not a single continuous execution.

Why does my function still time out at 15 minutes after I set Timeout to 5400?
The most common cause is that the function is not actually configured to run on Managed Instances compute. The extended timeout is specific to that execution mode and does not apply to standard Lambda functions even if you set a higher timeout value.

Can API Gateway-triggered functions use the 90-minute window?
No. API Gateway invocations are synchronous, and synchronous invocations remain limited to 15 minutes regardless of the function's underlying compute type. Route long-running work through SQS, EventBridge, or S3 event notifications instead.

What happens if my function is still running when the 90-minute limit is reached?
The invocation is forcibly terminated, similar to how the old 15-minute limit worked, just at a later point. This is exactly why checkpointing progress before the deadline, as shown in Step 3 and the complete project example, is essential rather than optional.

Does the Init phase (cold start) also get 90 minutes?
No. The Init phase remains limited to 15 minutes even on Managed Instances. Only the invocation phase itself benefits from the extended window for async and event source mapping triggers.

Related Coverage

Elias Virtanen

Elias Virtanen

Cybersecurity Analyst

Elias Virtanen is the Cybersecurity Analyst at Tech Insider, bringing hands-on expertise from his background in penetration testing and security consulting. He previously worked as a security researcher at F-Secure in Helsinki, where he focused on threat intelligence and vulnerability disclosure. Elias covers ransomware trends, zero-trust architecture, and the evolving regulatory landscape including NIS2 and the EU Cyber Resilience Act. He holds a CISSP certification and an MSc in Information Security from Aalto University.

View all articles