Amazon SQS Message Queue Setup for Web Application

Our company is engaged in the development, support and maintenance of sites of any complexity. From simple one-page sites to large-scale cluster systems built on micro services. Experience of developers is confirmed by certificates from vendors.
Development and maintenance of all types of websites:
Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Showing 1 of 1 servicesAll 2065 services
Amazon SQS Message Queue Setup for Web Application
Medium
~2-3 business days
FAQ
Our competencies:
Development stages
Latest works
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    822
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    847
  • image_website-sbh_0.png
    Website development for SBH Partners
    999
  • image_website-_0.png
    Website development for Red Pear
    451

Amazon SQS Message Queue Setup

Amazon SQS is a managed message queue service from AWS without need to administer a broker. Two types: Standard Queue (high throughput, possible duplicates) and FIFO Queue (guaranteed order, exactly once).

Creating queue via Terraform

# Dead Letter Queue
resource "aws_sqs_queue" "dlq" {
  name                      = "myapp-jobs-dlq"
  message_retention_seconds = 1209600  # 14 days
}

# Main queue
resource "aws_sqs_queue" "jobs" {
  name                       = "myapp-jobs"
  visibility_timeout_seconds = 300      # message processing time
  message_retention_seconds  = 86400    # 24 hours
  receive_wait_time_seconds  = 20       # long polling

  redrive_policy = jsonencode({
    deadLetterTargetArn = aws_sqs_queue.dlq.arn
    maxReceiveCount     = 3  # 3 failures → DLQ
  })
}

# FIFO queue (for ordered tasks)
resource "aws_sqs_queue" "orders_fifo" {
  name                        = "myapp-orders.fifo"
  fifo_queue                  = true
  content_based_deduplication = true
  deduplication_scope         = "messageGroup"
  fifo_throughput_limit       = "perMessageGroupId"
}

# IAM policy for application
resource "aws_iam_policy" "sqs_app" {
  name = "myapp-sqs-access"
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect = "Allow"
      Action = [
        "sqs:SendMessage",
        "sqs:ReceiveMessage",
        "sqs:DeleteMessage",
        "sqs:GetQueueAttributes",
      ]
      Resource = [aws_sqs_queue.jobs.arn, aws_sqs_queue.dlq.arn]
    }]
  })
}

PHP: AWS SDK

use Aws\Sqs\SqsClient;

class SqsQueue
{
    private SqsClient $client;
    private string $queueUrl;

    public function __construct()
    {
        $this->client = new SqsClient([
            'version' => 'latest',
            'region'  => config('aws.region', 'eu-west-1'),
        ]);
        $this->queueUrl = config('queue.connections.sqs.queue');
    }

    public function send(string $jobClass, array $payload, int $delaySeconds = 0): string
    {
        $result = $this->client->sendMessage([
            'QueueUrl'     => $this->queueUrl,
            'MessageBody'  => json_encode([
                'job'       => $jobClass,
                'payload'   => $payload,
                'attempts'  => 0,
                'sent_at'   => now()->toIso8601String(),
            ]),
            'DelaySeconds' => $delaySeconds,
            'MessageAttributes' => [
                'JobClass' => [
                    'DataType'    => 'String',
                    'StringValue' => $jobClass,
                ],
            ],
        ]);

        return $result['MessageId'];
    }

    public function poll(int $maxMessages = 10): void
    {
        $result = $this->client->receiveMessage([
            'QueueUrl'            => $this->queueUrl,
            'MaxNumberOfMessages' => $maxMessages,
            'WaitTimeSeconds'     => 20,   // long polling
            'VisibilityTimeout'   => 300,  // 5 minutes for processing
        ]);

        foreach ($result->get('Messages') ?? [] as $message) {
            $this->processMessage($message);
        }
    }

    private function processMessage(array $message): void
    {
        try {
            $body = json_decode($message['Body'], true);
            $job  = app($body['job']);
            $job->handle($body['payload']);

            $this->client->deleteMessage([
                'QueueUrl'      => $this->queueUrl,
                'ReceiptHandle' => $message['ReceiptHandle'],
            ]);
        } catch (\Throwable $e) {
            Log::error('SQS job failed', [
                'job'   => $body['job'] ?? 'unknown',
                'error' => $e->getMessage(),
            ]);
            // Message returns to queue after VisibilityTimeout expires
        }
    }
}

Laravel Queue with SQS

Laravel supports SQS out of the box:

QUEUE_CONNECTION=sqs
AWS_ACCESS_KEY_ID=AKIA...
AWS_SECRET_ACCESS_KEY=secret
AWS_DEFAULT_REGION=eu-west-1
SQS_QUEUE=https://sqs.eu-west-1.amazonaws.com/123456789/myapp-jobs
// Standard Laravel Job
class ProcessOrderJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public int $tries = 3;
    public int $timeout = 120;

    public function __construct(private int $orderId) {}

    public function handle(OrderService $service): void
    {
        $service->process($this->orderId);
    }

    public function failed(\Throwable $e): void
    {
        Log::error('Order processing failed', [
            'order_id' => $this->orderId,
            'error'    => $e->getMessage(),
        ]);
    }
}

// Publishing
ProcessOrderJob::dispatch($order->id);

// With 5 minute delay
ProcessOrderJob::dispatch($order->id)->delay(now()->addMinutes(5));

SQS + Lambda (serverless processing)

# Trigger Lambda from SQS
resource "aws_lambda_event_source_mapping" "sqs_lambda" {
  event_source_arn                   = aws_sqs_queue.jobs.arn
  function_name                      = aws_lambda_function.worker.arn
  batch_size                         = 10
  maximum_batching_window_in_seconds = 5
  function_response_types            = ["ReportBatchItemFailures"]
}
# Lambda handler (Python)
import json

def handler(event, context):
    failed_ids = []

    for record in event['Records']:
        try:
            body = json.loads(record['body'])
            process_job(body)
        except Exception as e:
            print(f"Failed: {record['messageId']}: {e}")
            failed_ids.append({'itemIdentifier': record['messageId']})

    # Partial batch failure — only failed items return to queue
    return {'batchItemFailures': [{'itemIdentifier': id} for id in failed_ids]}

Monitoring

CloudWatch SQS metrics: ApproximateNumberOfMessagesVisible (queue size), NumberOfMessagesSent, NumberOfMessagesDeleted, ApproximateAgeOfOldestMessage.

resource "aws_cloudwatch_metric_alarm" "sqs_depth" {
  alarm_name          = "sqs-queue-depth"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = 2
  metric_name         = "ApproximateNumberOfMessagesVisible"
  namespace           = "AWS/SQS"
  period              = 60
  statistic           = "Maximum"
  threshold           = 1000
  alarm_actions       = [aws_sns_topic.alerts.arn]

  dimensions = { QueueName = aws_sqs_queue.jobs.name }
}

Implementation timeline

Laravel Queue + SQS: 1 day (driver is built-in). Custom PHP/Node.js consumer with DLQ and monitoring: 2–3 days. SQS + Lambda serverless: 2–3 days.