SQS#
AWS-managed message queue service.
Configuration#
Crossplane Composition Config (XRD for transport configuration):
apiVersion: asya.dev/v1alpha1
kind: SQSTransport
metadata:
name: sqs-default
spec:
region: us-east-1
endpoint: "" # Optional, for LocalStack or custom SQS endpoints
visibilityTimeout: 300 # Optional, seconds, defaults to 300 (5 minutes)
waitTimeSeconds: 20 # Optional, long polling, defaults to 20
queues:
autoCreate: true # Optional, defaults to true
forceRecreate: false # Optional, defaults to false
dlq:
enabled: true # Optional
maxRetryCount: 3 # Optional, defaults to 3
retentionDays: 14 # Optional, defaults to 14
tags: # Optional, tags applied to created queues
Environment: production
Team: ml-platform
Sidecar environment variables (rendered by Crossplane composition):
ASYA_TRANSPORT=sqsASYA_AWS_REGION→ fromconfig.regionASYA_SQS_ENDPOINT→ fromconfig.endpoint(optional)ASYA_SQS_VISIBILITY_TIMEOUT→ fromconfig.visibilityTimeout(optional)ASYA_SQS_WAIT_TIME_SECONDS→ fromconfig.waitTimeSeconds(optional)
Queue Creation#
Crossplane Composition creates SQS queues automatically when AsyncActor is reconciled:
Queue name: asya-{namespace}-{actor_name}
Example: Actor text-processor in namespace default → Queue asya-default-text-processor
Queue URL: https://sqs.{region}.amazonaws.com/{account}/asya-{namespace}-{actor_name}
IAM Permissions#
Sidecar permissions (via IRSA, Pod Identity, or instance role):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sqs:ReceiveMessage",
"sqs:SendMessage",
"sqs:DeleteMessage",
"sqs:ChangeMessageVisibility",
"sqs:GetQueueAttributes",
"sqs:GetQueueUrl"
],
"Resource": "arn:aws:sqs:*:*:asya-*"
}
]
}
Crossplane Provider permissions:
{
"Effect": "Allow",
"Action": [
"sqs:CreateQueue",
"sqs:DeleteQueue",
"sqs:SetQueueAttributes",
"sqs:GetQueueAttributes",
"sqs:GetQueueUrl",
"sqs:TagQueue"
],
"Resource": "arn:aws:sqs:*:*:asya-*"
}
KEDA permissions (for autoscaling):
{
"Effect": "Allow",
"Action": [
"sqs:GetQueueAttributes",
"sqs:GetQueueUrl",
"sqs:ListQueues"
],
"Resource": "arn:aws:sqs:*:*:asya-*"
}
KEDA Scaler#
triggers:
- type: aws-sqs-queue
metadata:
queueURL: https://sqs.us-east-1.amazonaws.com/.../asya-actor
queueLength: "5"
awsRegion: us-east-1
DLQ Configuration#
When queues.dlq.enabled: true, Crossplane creates DLQ for each queue:
DLQ name: asya-{namespace}-{actor_name}-dlq
Max receive count: Configured via queues.dlq.maxRetryCount (default: 3)
Retention: Configured via queues.dlq.retentionDays (default: 14 days)
Behavior: Messages move to DLQ after exceeding max receive count.
Implementation Details#
Long polling: Sidecar uses waitTimeSeconds for efficient message retrieval (default: 20s)
Visibility timeout: Messages become invisible to other consumers for visibilityTimeout seconds (default: 300s)
Nack behavior: Nack() sets visibility timeout to 0, making message immediately available for redelivery
Queue URL caching: Sidecar caches resolved queue URLs to reduce API calls
Reconnection: SQS client supports automatic reconnection with exponential backoff
Best Practices#
- Use IRSA or Pod Identity for pod-level IAM permissions
- Set
visibilityTimeoutlonger than expected processing time - Monitor DLQ depth for stuck messages
- Use
asya-prefix for IAM policy granularity - Enable DLQ for production workloads
- Set appropriate
tagsfor cost tracking
Cost Considerations#
- First 1M requests/month free
- $0.40 per million requests after
- No idle costs (pay per use)
- Scale to zero = $0
See: AWS SQS Pricing