SQS
Simple Queue Service
🎯 Sebab Apa Wujud
Wujud sebab kalau service A panggil service B terus (synchronous), bila B sibuk/down → A tersekat/gagal, dan bila trafik melonjak B kena hentam terus sampai pengsan. SQS letak "baris gilir" di tengah: A campak mesej masuk queue & teruskan kerja, B amik (pull) ikut kadar SENDIRI. Kalau B mati, mesej tunggu dalam queue (tak hilang) sampai B sihat balik. Tujuan: decouple service + serap lonjakan (buffer) + tahan kegagalan (retry/DLQ).
Apa Dia
Mengurus queue untuk menghantar mesej antara komponen aplikasi secara asynchronous. Standard queue: at-least-once delivery, best-effort ordering. FIFO queue: exactly-once, strict order.
SQS Key Concepts
Visibility Timeout → Message invisible semasa diproses (max 12 jam). Jika consumer mati sebelum siap → message visible semula selepas timeout
Delay Seconds → Delay sebelum message pertama kali visible dalam queue (max 15 minit)
Dead Letter Queue (DLQ) → Message yang gagal diproses N kali dihantar ke DLQ untuk debug
Message Retention → Default 4 hari, max 14 hari
Lambda producer → SQS → Lambda consumer (throttling fix)
Exam pattern: pecah 1 Lambda jadi 2 — producer ACK cepat (return selepas enqueue), SQS buffer burst, consumer poll & proses ikut kadar sendiri → kurang 429 throttle. SNS SALAH: push real-time, tak buffer. DAX/DynamoDB SALAH: root cause = Lambda concurrency, bukan DB read cache. INGAT: "throttling / acknowledge when accepted / decouple" → SQS antara 2 Lambda.
Pilih messaging service — SQS vs SNS vs EventBridge vs Amazon MQ (decision tree)
Tanya ikut urutan: (1) legacy broker? → Amazon MQ. (2) route ikut isi / event AWS / cron? → EventBridge. (3) satu-ke-ramai serentak? → SNS. (4) selainnya, buffer & pull → SQS. INGAT exam: SQS = pull & buffer · SNS = push & broadcast · EventBridge = route pintar · Amazon MQ = jambatan legacy.
Analogi — 4 cara hantar mesej di pejabat
Kaitkan dengan familiar: pos = beratur & pull (SQS), pembesar suara surau = broadcast serentak (SNS), switchboard = route ikut jenis (EventBridge), adapter palam = sambung legacy ke cloud (Amazon MQ). INGAT exam: "decouple/buffer" → SQS, "notify many/fan-out" → SNS, "route by content/schedule" → EventBridge, "migrate existing broker" → Amazon MQ.
DLQ — aliran mesej gagal + analogi Kotak Surat Mati
Analogi: posmen (consumer) cuba hantar surat rosak 3 kali (maxReceiveCount), asyik gagal → ketua pos lempar masuk Kotak Surat Mati (DLQ) supaya surat lain tak tersekat; pegawai siasat (developer) buka kotak kaji punca, lepas betul tekan Redrive hantar balik. INGAT exam: "mesej corrupt/poison pill blok queue, nak isolate & debug" → DLQ + maxReceiveCount; "hantar balik lepas fix" → Redrive.
Cross-account SQS — "Dua Kunci" (analogi Ali hantar surat ke Peti Syarikat B)
Kaitkan dengan familiar: Ali (Syarikat A) nak masuk surat ke Peti-SQS (Syarikat B). Syarikat A bagi Ali pas keluar (IAM Policy, Resource = ID akaun B). Syarikat B tulis memo kat pengawal peti (Queue Policy, Principal = ID akaun A:root). Dua-dua belah WAJIB izin — set satu belah je → pintu tutup, Access Denied. INGAT exam: cross-account SQS = IAM policy (source) AND SQS queue policy (destination, ada Principal).
Standard vs FIFO queue
| Aspect | Standard | FIFO |
|---|---|---|
| Ordering | Best-effort (can arrive out of order) | 🟢 Strict order (per MessageGroupId) |
| Delivery | At-least-once (can duplicate) | Exactly-once (deduplication) |
| Throughput | Nearly unlimited | 300 msg/s (3000 with batching) |
| Name suffix | any | must end in .fifo |
| Use when | Max throughput, dupes OK | Order + no duplicates matter |
Ingat: "Duplicate processing must be eliminated" or "order must be preserved" → FIFO. Default high-throughput decoupling → Standard.
Cross-account SQS — rupa JSON Kunci 1 (IAM, source) vs Kunci 2 (Queue Policy, destination)
| Aspect | Kunci 1 — IAM Policy | Kunci 2 — SQS Queue Policy |
|---|---|---|
| Lekat di mana | Source Account 1111 (pada user/role Ali) | Destination Account 2222 (pada queue itu sendiri) |
| Jenis policy | Identity-based | Resource-based |
| Ada "Principal"? | ❌ Tiada (dah tahu siapa — Ali) | 🟢 WAJIB ada → "AWS": "arn:aws:iam::1111:root" |
| Effect / Action | Allow · sqs:SendMessage | Allow · sqs:SendMessage |
| "Resource" ID | arn:...:2222:Peti-SQS (ID akaun DESTINATION) | arn:...:2222:Peti-SQS (queue sendiri) |
| Maksud | "Ali dibenarkan hantar KELUAR ke queue akaun 2222" | "Aku (queue) percaya root akaun 1111 hantar masuk" |
Ingat: Cara baca cepat: Principal HANYA wujud di resource-based policy (Kunci 2) — itu cara nak kenal mana satu. IAM (Kunci 1) sebut ID akaun destination dalam Resource; Queue Policy (Kunci 2) sebut ID akaun source dalam Principal. Silang ID = corak cross-account. Set satu belah je → Access Denied. Exam: pangkah jawapan "IAM policy sahaja" atau "queue policy sahaja".
⚡ Quick Sifir — hafal ni
- ▪SQS = PULL queue, satu mesej diproses oleh SATU consumer. SNS = PUSH ke ramai
- ▪Standard = at-least-once (boleh duplicate) + best-effort order. FIFO = exactly-once + strict order
- ▪Order penting / no duplicate → FIFO (.fifo, 300/s atau 3000 batch)
- ▪Visibility Timeout < masa proses → mesej muncul balik → DUPLICATE. Naikkan timeout
- ▪Cross-account hantar ke queue → SQS queue policy (resource-based), bukan IAM je
- ▪Long polling (WaitTime>0, max 20s) → kurangkan empty response & kos API
- ▪DLQ = SQS queue asing untuk mesej gagal. Cetus bila ReceiveCount > maxReceiveCount
- ▪Poison pill (data corrupt) → DLQ, kalau tak server pusing proses sampai bil melambung
- ▪DLQ source FIFO → DLQ kena FIFO juga; source Standard → DLQ kena Standard
- ▪Lepas fix bug → DLQ Redrive tolak balik mesej ke queue utama, tak payah tulis kod
- ▪Scale consumer (ECS/EC2) ikut queue backlog BUKAN CPU/Memory — CPU rendah walau queue penuh sebab container proses satu-satu. Guna custom metric ApproximateNumberOfMessagesVisible atau backlog per task (queue depth ÷ target capacity)
💡 Exam Scenario
Spot instance terminated masa process SQS message → message TIDAK hilang. Ia akan visible semula selepas Visibility Timeout expired. Message hanya deleted bila consumer call DeleteMessage API selepas berjaya process.
🪤 Perangkap Soalan
Q: Sistem pembayaran proses mesej dua kali kadang-kadang, dan susunan transaksi mesti tepat. Queue SQS sedia ada Standard. Pembetulan minimum?
⚠ Umpan: Tambah logik dedup & susun semula dalam kod aplikasi consumer. Nampak betul sebab "betulkan dalam kod".
✓ Betul: Tukar ke SQS FIFO queue — ia bagi exactly-once (deduplication) + strict ordering per MessageGroupId secara built-in, perubahan kod minimum. Standard memang at-least-once + best-effort order. Keyword "no duplicates / order preserved" → FIFO.
Q: Consumer EC2 (Spot) ditamatkan separuh jalan semasa memproses mesej SQS. Adakah mesej hilang?
⚠ Umpan: Ya, hilang — sebab consumer dah amik mesej tu dari queue dan mati sebelum siap. Nampak betul sebab "dah diambil".
✓ Betul: TIDAK hilang. Mesej cuma jadi INVISIBLE semasa Visibility Timeout; sebab consumer tak panggil DeleteMessage, ia jadi VISIBLE semula lepas timeout dan consumer lain proses. Mesej hanya hilang bila DeleteMessage dipanggil selepas berjaya. Keyword "consumer dies mid-processing" → mesej selamat (visibility timeout).
Q: App ECS ingest file (PDF/JPEG/DOCX) async & upload ke DMS. Masa campaign trafik naik 500%, kadang upload gagal → file HILANG sebab tak disimpan sementara. Pilih redesign: (A) S3 simpan file + SQS queue request, (B) RDS simpan file + SNS notify, (C) DynamoDB simpan metadata file + Lambda proses upload, (D) EFS simpan file + Amazon MQ.
⚠ Umpan: C (DynamoDB + Lambda) paling menipu — Lambda nampak "auto-scale untuk burst" & DynamoDB nampak "tempat simpan". TAPI DynamoDB simpan METADATA je (nama/saiz/status), BUKAN file sebenar — ada had 400 KB per item, PDF/DOCX tak muat. Jadi root cause "file tak disimpan" MASIH tak selesai → file tetap hilang. B (RDS) salah: RDS bukan untuk binary blob besar + mahal; SNS = notify, bukan buffer. D (EFS+MQ) salah: EFS mahal vs S3, Amazon MQ untuk legacy broker — bukan cost-efficient.
✓ Betul: A — S3 simpan FILE sebenar (durable 11 nines, murah, scale auto → file tak hilang walau upload ke DMS gagal) + SQS buffer/decouple request masa burst 500% (DMS sibuk → mesej tunggu dalam queue, proses ikut kadar DMS). Keyword: "file hilang sebab tak disimpan" → simpan file kat S3 (BUKAN RDS/DynamoDB); "burst + async + jangan hilang" → SQS. INGAT: simpan FILE = S3; simpan METADATA = DynamoDB.
Q: Data lake terpusat dalam Analytics Account ada satu SQS queue. App dalam BANYAK account lain perlu hantar (SendMessage) ke queue terpusat tu. Cara paling efficient & scalable? (A) IAM policy dalam Analytics Account bagi SendMessage ke account lain, (B) SQS queue policy bagi SendMessage ke account lain, (C) IAM role dalam Analytics Account, account lain assume role tu untuk hantar, (D) Both B and C valid & sama efficient.
⚠ Umpan: D "Both B and C valid" paling menipu — sebab C (assume role) MEMANG boleh jadi (account lain assume role → dapat temp creds → SendMessage), jadi nampak "dua-dua betul". TAPI exam tanya paling EFFICIENT & SCALABLE: C paksa setiap account buat STS AssumeRole dulu (extra hop + kena urus trust setiap account) → meleret bila account makin ramai. A pula salah konsep: IAM policy dalam Analytics Account urus apa principal Analytics SENDIRI boleh buat — ia TAK boleh "bagi" account lain akses; cross-account grant kena datang dari sisi resource.
✓ Betul: B — SQS queue policy (resource-based) pada queue, terus sebut Principal account lain + Allow SendMessage. Satu policy kat queue cover semua account (boleh guna kondisi aws:PrincipalOrgID untuk seluruh Org sekali gus), takde assume-role hop. Keyword "allow OTHER accounts to send to centralized SQS" → SQS queue policy (resource-based), BUKAN IAM policy sahaja, BUKAN assume-role (over-engineered untuk hantar mesej je).
Q: Satu mesej dalam queue ada data corrupt — consumer cuba proses, crash, mesej balik queue, cuba lagi, crash lagi… berulang sampai blok mesej lain & bil naik. Kau nak isolate mesej bermasalah tu untuk debug tanpa ganggu trafik live. Apa setup terbaik?
⚠ Umpan: Naikkan Visibility Timeout supaya mesej tu "rehat" lama-lama, atau tambah logik retry + try/catch dalam kod consumer. Nampak betul sebab "uruskan mesej gagal". SALAH: naikkan visibility timeout cuma LAMBATKAN mesej muncul balik — ia tetap balik & crash lagi (loop tak putus). Retry dalam kod pun masih pusing benda corrupt yang sama (poison pill) selamanya.
✓ Betul: Setup Dead-Letter Queue (DLQ) + set maxReceiveCount (cth 3) pada source queue. Lepas mesej gagal diproses 3 kali (ReceiveCount > maxReceiveCount), SQS AUTO pindahkan ia keluar dari queue utama masuk DLQ → trafik live jalan semula, developer bedah mesej dalam DLQ asingan. Keyword "corrupt/poison message blok queue + isolate untuk debug" → DLQ + maxReceiveCount, BUKAN visibility timeout, BUKAN retry dalam kod.
Q: E-commerce (EC2 + ALB + RDS) jangka lonjakan WRITE besar masa product launch. RDS hampir cecah IOPS limit; vertical scaling tak nak sebab bajet. Cara cost-effective handle write-heavy? (A) Tambah RDS Read Replica, (B) Letak SQS queue depan — app tulis ke queue, consumer proses ke RDS ikut kadar mampu, (C) Upgrade instance class RDS, (D) Migrate ke DynamoDB.
⚠ Umpan: A (Read Replica) paling menipu — nampak "scaling RDS" terus pilih. TAPI Read Replica scale READ je (offload SELECT); ia LANGSUNG tak bantu WRITE — malah write kena replicate ke replica juga. C (upgrade instance) = vertical scaling, dah dikecualikan (bajet). D (DynamoDB) = re-architecture besar, mahal & berisiko untuk relational e-commerce, bukan "cost-effective minimal change".
✓ Betul: B — SQS di depan RDS (queue-based load leveling): app campak write request masuk queue, consumer proses ke RDS ikut kadar yang RDS MAMPU. Lonjakan write diserap dalam queue (buffer) → RDS tak kena hentam lebih IOPS limit. Murah (SQS sen je) + tak perlu vertical scaling. Keyword "write-heavy spike / nearing IOPS limit / cost-effective / no vertical scaling" → SQS buffer writes (queue-based load leveling). INGAT: Read Replica = READ scaling, BUKAN write.
Q: API Gateway → Lambda terima 5KB JSON, simpan ke Aurora. App cuma perlu ACK bila request diterima (bukan bila siap proses). Banyak Lambda throttle (429), terpaksa naikkan concurrent execution berkali-kali. Fix?
⚠ Umpan: Pecah 2 Lambda + SNS antara keduanya — SNS nampak "signal work" macam queue. SALAH: SNS PUSH real-time ke subscriber; bila burst, consumer Lambda masih kena hentam serentak = masih throttle.
✓ Betul: Pecah 2 Lambda + SQS di tengah — producer enqueue & return cepat; SQS BUFFER burst; consumer poll ikut kadar (Event Source Mapping + backoff bila throttle). Keyword "acknowledge when accepted / throttling / decouple" → SQS, BUKAN SNS. DAX/DynamoDB tak selesai root cause (Lambda concurrency, bukan DB read).
🧠 Cara Mudah Ingat
- →Cross-account SQS access: guna SQS RESOURCE-BASED policy (queue policy) pada queue — bukan IAM policy dalam source account
- →IAM policy dalam target account SAHAJA tidak cukup untuk cross-account SQS access. Queue policy mesti explicitly allow source account principal
- →Exam: "allow another AWS account to send messages to SQS queue" → SQS queue policy (resource-based)
- →Long Polling (ReceiveMessageWaitTimeSeconds > 0, max 20s): consumer WAITS for message before returning. Reduces empty responses + API call costs. Short polling = returns immediately even if empty.
- →Visibility Timeout: message hidden from OTHER consumers after retrieved. If processing takes longer than timeout → message becomes visible again → DUPLICATE processing. Fix: increase timeout to exceed max processing time, or use ChangeMessageVisibility mid-processing.
- →Duplicate messages: Standard queue = at-least-once delivery (can duplicate). FIFO queue = exactly-once delivery with deduplication. Switch to FIFO to eliminate duplicates with minimal code change.
- →Batch operations: ReceiveMessage gets up to 10 messages per call; DeleteMessageBatch deletes up to 10 per call. Use batching to reduce API call count and costs.
- →SNS→SQS→Lambda pattern: add SQS queue between SNS and Lambda for reliable async processing. If Lambda fails transiently, message waits in SQS and is retried — no message loss, no manual intervention.
- →SQS FIFO + Lambda: message ordering within MessageGroupId guaranteed. Requires event source mapping (ESM) to connect Lambda to FIFO queue.
- →DLQ (Dead-Letter Queue): setup via RedrivePolicy pada SOURCE queue, set maxReceiveCount. Bila ReceiveCount > maxReceiveCount → SQS auto-move mesej ke DLQ. DLQ sendiri queue SQS biasa.
- →Poison pill = mesej corrupt yang asyik gagal proses. Tanpa DLQ → consumer pusing proses benda sama berulang → kos & throughput terbakar. DLQ keluarkan ia supaya queue utama jalan semula.
- →DLQ jenis mesti SAMA dengan source: source FIFO → DLQ FIFO; source Standard → DLQ Standard. Salah jenis = tak boleh attach.
- →DLQ Redrive: lepas developer fix bug, guna Redrive (console / StartMessageMoveTask API) tolak balik mesej dari DLQ ke queue utama untuk reproses — tak perlu tulis kod pindah manual.
- →DLQ retention: kira dari masa mesej MASUK queue ASAL (bukan masa masuk DLQ). Set retention DLQ lebih panjang (cth 14 hari) supaya ada masa debug sebelum mesej luput.
- →Exam trigger: "messages failing repeatedly block the queue" / "isolate & analyze corrupted messages separately" → Dead-Letter Queue + tune maxReceiveCount (BUKAN naikkan visibility timeout, BUKAN retry dalam kod).
- →Queue-based scaling (SQS + ASG/ECS): scale consumer ikut queue backlog, BUKAN CPU/Memory. CPU/Memory BUTA terhadap barisan queue (container proses satu-satu → CPU kekal rendah walau 10,000 mesej sangkut). Guna custom metric ApproximateNumberOfMessagesVisible (CloudWatch) atau backlog per task (queue depth ÷ ECS target capacity) → Target Tracking scale out bila backlog tinggi. Keyword "scale based on SQS queue" → custom metric backlog, BUKAN CPU/Memory.
- →PRICING (us-east-1): SQS Standard ~$0.40 per 1M requests; FIFO ~$0.50/1M (more expensive). Free tier 1M requests/mo (Standard). 1 request = any API call (SendMessage, ReceiveMessage, DeleteMessage) — BUKAN ikut tempoh queue hidup. Jimat kos: (1) BATCHING — up to 10 messages per request → 10x kurang request bill; (2) LONG POLLING (WaitTimeSeconds>0) → kurang empty-poll request. Payload >256KB → simpan kat S3 + SQS message rujuk je (Extended Client Library).
Guna Bila
Decouple services, async queue