If you’re triggering a Lambda function from an SQS queue, you may hit this error during deployment:
Invalid request provided: Queue visibility timeout: 30 seconds is less than Function timeout: 300 seconds
This means your SQS queue’s visibility timeout is shorter than your Lambda function’s timeout. AWS blocks this configuration because it causes duplicate message processing. This guide explains why the error happens and how to fix the SQS visibility timeout in AWS Lambda correctly.
Why This Happens
When Lambda polls a message from SQS, that message becomes invisible to other consumers for the duration of the visibility timeout. If Lambda takes longer to process the message than the visibility timeout allows, SQS assumes processing failed and makes the message visible again. Another Lambda invocation picks it up, and now you have two invocations processing the same message.
This leads to:
- Duplicate processing (double charges, repeated emails, duplicate database writes)
- Data inconsistency across systems
- Wasted compute from redundant invocations
With the default SQS visibility timeout of 30 seconds and a Lambda timeout of 300 seconds, any invocation running longer than 30 seconds triggers a retry — even though the original is still running.
The Fix: Set Visibility Timeout to 6x Lambda Timeout
AWS recommends setting the queue’s visibility timeout to at least 6 times the Lambda function timeout, plus the MaximumBatchingWindowInSeconds value if you use batching. This accounts for the function’s execution time and allows room for Lambda to retry on throttling errors before the message becomes visible again.
For a Lambda function with a 300-second (5-minute) timeout:
- Minimum visibility timeout:
300 × 6 = 1800 seconds(30 minutes) - With a 5-second batching window:
(300 × 6) + 5 = 1805 seconds
The maximum visibility timeout for an SQS queue is 12 hours (43,200 seconds).
Configuring with AWS CLI
If your queue already exists, update the visibility timeout directly:
aws sqs set-queue-attributes \
--queue-url https://sqs.ap-southeast-1.amazonaws.com/123456789012/my-queue \
--attributes VisibilityTimeout=1800 \
--region ap-southeast-1
Verify the change:
aws sqs get-queue-attributes \
--queue-url https://sqs.ap-southeast-1.amazonaws.com/123456789012/my-queue \
--attribute-names VisibilityTimeout \
--region ap-southeast-1
You can also update this in the SQS console under Queue > Edit > Visibility timeout.
Configuring with CloudFormation
If you manage your infrastructure as code, define both the main queue and a dead letter queue (DLQ) in your CloudFormation template:
Resources:
MainQueue:
Type: AWS::SQS::Queue
Properties:
QueueName: my-queue
VisibilityTimeout: 1800
RedrivePolicy:
deadLetterTargetArn: !GetAtt DeadLetterQueue.Arn
maxReceiveCount: 3
DeadLetterQueue:
Type: AWS::SQS::Queue
Properties:
QueueName: my-queue-dlq
VisibilityTimeout: 60
MessageRetentionPeriod: 1209600
MyFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: my-function
Handler: src/handler.lambda_handler
Runtime: python3.12
Timeout: 300
SQSEventSource:
Type: AWS::Lambda::EventSourceMapping
Properties:
EventSourceArn: !GetAtt MainQueue.Arn
FunctionName: !Ref MyFunction
BatchSize: 10
VisibilityTimeout: 1800— 6x the Lambda timeout of 300 secondsmaxReceiveCount: 3— after 3 failed attempts, the message moves to the DLQMessageRetentionPeriod: 1209600— keeps DLQ messages for 14 days before automatic deletion
Configuring with Serverless Framework
The same configuration in serverless.yml:
functions:
myFunction:
handler: src/handler.lambda_handler
timeout: 300
resources:
Resources:
MainQueue:
Type: AWS::SQS::Queue
Properties:
QueueName: ${sls:stage}-my-queue
VisibilityTimeout: 1800
RedrivePolicy:
deadLetterTargetArn: !GetAtt DeadLetterQueue.Arn
maxReceiveCount: 3
DeadLetterQueue:
Type: AWS::SQS::Queue
Properties:
QueueName: ${sls:stage}-my-queue-dlq
VisibilityTimeout: 60
MessageRetentionPeriod: 1209600
Handling Failed Messages with a Dead Letter Queue
A dead letter queue (DLQ) captures messages that fail processing after maxReceiveCount attempts. Without a DLQ, failed messages keep cycling between the queue and Lambda until the message retention period expires.
Lambda does not automatically retry messages from the DLQ. To reprocess them, you can:
- Use SQS dead-letter queue redrive in the console — select the DLQ, choose “Start DLQ redrive”, and move messages back to the main queue
- Write a separate Lambda function that polls the DLQ and reprocesses or routes the messages
- Manually inspect and replay messages using the AWS CLI
If your processing involves long-running or multi-step workflows, consider using Step Functions instead of a single Lambda. For an example of this pattern, see How to Avoid AWS Lambda Timeout When Processing HubSpot Records.
Monitoring SQS and Lambda
Watch these CloudWatch metrics to catch visibility timeout issues early:
| Metric | What It Tells You |
|---|---|
ApproximateNumberOfMessagesVisible |
Messages waiting to be processed — a growing number means Lambda can’t keep up |
ApproximateNumberOfMessagesNotVisible |
Messages currently being processed (in-flight) |
NumberOfMessagesReceived |
Total messages received — compare with NumberOfMessagesDeleted to spot retries |
ApproximateAgeOfOldestMessage |
How long the oldest message has been in the queue — high values indicate a processing backlog |
Set a CloudWatch alarm on the DLQ’s ApproximateNumberOfMessagesVisible metric. Any message landing in the DLQ means something failed, and you want to know about it immediately. For cleaning up old Lambda logs generated during debugging, see How to Delete AWS Lambda Logs from CloudWatch using Python Scripts.
Quick Reference
| Setting | Value |
|---|---|
| Main queue visibility timeout | 6x Lambda timeout (e.g., 1800s for a 300s function) |
| DLQ visibility timeout | 60 seconds |
| DLQ max receive count | 3–5 attempts |
| DLQ message retention | 14 days (1209600 seconds) |
| Maximum visibility timeout | 12 hours (43,200 seconds) |
Conclusion
The fix is straightforward: set your SQS queue’s visibility timeout to at least 6x your Lambda function’s timeout. Pair it with a dead letter queue and a CloudWatch alarm on the DLQ to catch failures early.
For more on how Lambda receives and processes messages, see Understanding Lambda’s Event and Context Parameters. If you’re building cross-account messaging with SQS, check out Setting Up Cross-Account SNS to SQS Subscription in AWS.


