Build an SQS Worker Environment with Python on Elastic Beanstalk¶
This recipe shows how to pair a Python worker environment with Amazon SQS for asynchronous job processing. It is useful when background tasks should not run in the web request path.
Prerequisites¶
- Running Python Elastic Beanstalk application.
- Permission to create and use Amazon SQS queues.
- Separate worker environment or plan to create one.
- Flask application code that can process queued jobs.
What You'll Build¶
You will build a worker tier environment that receives messages from Amazon SQS and processes them through a Flask application endpoint.
flowchart LR
A[Web Environment] --> B[Amazon SQS Queue]
B --> C[Elastic Beanstalk Worker Environment]
C --> D[Flask Worker Handler] Steps¶
Step 1: Create a queue for background jobs¶
Step 2: Create or update the worker environment¶
aws elasticbeanstalk create-environment \
--application-name "$APP_NAME" \
--environment-name "$ENV_NAME-worker" \
--solution-stack-name "64bit Amazon Linux 2023 v4.3.2 running Python 3.11" \
--tier Name=Worker,Type=SQS/HTTP,Version=\"1.0\" \
--option-settings Namespace=aws:elasticbeanstalk:sqsd,OptionName=WorkerQueueURL,Value="https://sqs.$REGION.amazonaws.com/<account-id>/$APP_NAME-worker" \
--region "$REGION"
Step 3: Add a worker endpoint to the Flask app¶
import json
from flask import Flask, request
application = Flask(__name__)
@application.post("/worker")
def worker():
payload = json.loads(request.data)
return {"processed": payload["job_type"]}
Step 4: Send messages from the web app or CLI¶
import json
import boto3
sqs = boto3.client("sqs")
def enqueue_job(queue_url: str, job_type: str) -> None:
sqs.send_message(
QueueUrl=queue_url,
MessageBody=json.dumps({"job_type": job_type})
)
Step 5: Deploy and test background processing¶
eb deploy --staged
aws sqs send-message \
--queue-url "https://sqs.$REGION.amazonaws.com/<account-id>/$APP_NAME-worker" \
--message-body '{"job_type":"email"}' \
--region "$REGION"
Verification¶
eb logs --all
aws sqs get-queue-attributes \
--queue-url "https://sqs.$REGION.amazonaws.com/<account-id>/$APP_NAME-worker" \
--attribute-names ApproximateNumberOfMessages \
--region "$REGION"
Expected result: worker logs show message processing and the queue depth returns to zero after successful consumption.
Clean Up¶
aws elasticbeanstalk terminate-environment \
--environment-name "$ENV_NAME-worker" \
--terminate-resources \
--region "$REGION"
aws sqs delete-queue \
--queue-url "https://sqs.$REGION.amazonaws.com/<account-id>/$APP_NAME-worker" \
--region "$REGION"