ผ่าสถาปัตยกรรม Arcjet: สร้างระบบ Security ที่ต้องตัดสินใจใน 25ms ด้วย Go, Wasm และ ClickHouse

ในฐานะ Software Engineer เรามักเจอปัญหาโลกแตก: "อยากให้ระบบปลอดภัย (Security) แต่ก็กลัวระบบอืด (Latency)" การใส่ Rate Limiting, Bot Detection หรือ Email Validation เข้าไปใน Request flow มักแลกมาด้วยเวลาประมวลผลที่เพิ่มขึ้น แต่ Arcjet (แพลตฟอร์ม Security สำหรับ Developer) ตั้งโจทย์หินว่า ทุกการตัดสินใจต้องเกิดขึ้นภายใน 25ms (p95) วันนี้ผมจะพาไปผ่า Tech Stack ของ Arcjet ดูว่าเขาออกแบบสถาปัตยกรรมอย่างไรให้รองรับ High-throughput โดยที่ Latency ต่ำเตี้ยเรี่ยดินขนาดนั้นครับ
sandwiched-arcjet-tech-stack-behind-the-scene-cover-image
arcjet-tech-architecture-diagram
Arcjet tech architecture diagram

1. The Core Strategy: การทำ Local-First ด้วย WebAssembly (Wasm)

ความลับแรกของ Arcjet ไม่ใช่แค่ Server ที่แรง แต่คือการพยายามไม่ยิง Request ไปหา Server ถ้าไม่จำเป็น

Arcjet เลือกใช้กลยุทธ์ Embed Logic ฝังสมองลงไปใน SDK ที่รันอยู่บนแอปฯ ของเราเลย

  • Rust as the Source of Truth: Logic การตัดสินใจหลัก (เช่น กฎการกรอง Bot) ถูกเขียนด้วยภาษา Rust เพราะต้องการความเร็วและความปลอดภัย
  • Compile to Wasm: โค้ด Rust จะถูกคอมไพล์เป็น WebAssembly (Wasm) แล้วฝังลงไปใน SDK ของภาษาต่างๆ
  • Why? วิธีนี้ทำให้ Logic เหมือนกันเป๊ะไม่ว่าจะรันบน Node.js, Python หรือ Go และทำงานได้เร็วกว่าการเขียน Logic ซ้ำด้วยภาษานั้นๆ

2. The Hot Path: Decision API (หัวใจของ 25ms Latency)

นี่คือจุดที่สำคัญที่สุดของบทความนี้ครับ ตัวเลข 25ms (p95) ที่ Arcjet การันตี มันคือ Round-trip Time ของส่วนนี้โดยเฉพาะ

25ms คือค่าอะไรกันแน่?

มันคือเวลาตั้งแต่ SDK ส่งคำถามว่า Request นี้ผ่านได้ไหม? วิ่งไปที่ Server ของ Arcjet -> ประมวลผล -> และ ส่งคำตอบ Allow/Deny กลับมาถึง App เรา

ทำไมต้องซีเรียสกับเลขนี้? เพราะกระบวนการนี้เป็น Blocking Operation ครับ หมายความว่า User ของเราจะต้องรอจนกว่ากระบวนการนี้จะจบ ถ้าตรงนี้ช้า เว็บเราก็จะอืดทันที Arcjet จึงต้องเลือก Tech Stack ที่เร็วที่สุดเท่าที่จะทำได้:

  • Language: เลือกใช้ Go ทั้งหมด เพราะจัดการ Concurrency ได้เทพและ Latency ต่ำ
  • Protocol: ใช้ gRPC (ผ่าน ConnectRPC) เพื่อความกระชับและรวดเร็ว แต่ยังใจดีรองรับ HTTP/1.1 + JSON สำหรับ Client ที่ไม่รองรับ gRPC
  • Data Stores:
    • Rate Limiting: ใช้ Valkey (Fork ของ Redis) รันบน AWS ElastiCache โดยเขียน Logic ด้วย Lua Script เพื่อความเร็วระดับ Atomic
    • Dynamic Rules: กฎต่างๆ เก็บใน DynamoDB เพื่อใช้ฟีเจอร์ Global Replication ส่งข้อมูลไปทั่วโลกให้ใกล้ User ที่สุด
  • Server-Side Wasm: ที่เจ๋งคือ Backend Go ของเขาก็รัน Logic ตัวเดียวกับ SDK โดยใช้ Wazero ซึ่งเป็น Wasm Runtime ของ Go เพื่อให้มั่นใจว่าการตัดสินใจเหมือนกัน 100%

3. The Cold Path: Analytics Pipeline (Async & Decoupled)

หลังจากได้คำตอบ (Allow/Deny) ภายใน 25ms แล้ว ข้อมูล Log จะถูกส่งไปเก็บเพื่อวิเคราะห์ทีหลัง ส่วนนี้ Arcjet แยกออกมาเป็น Background Process (Cold Path) ทันที เพื่อไม่ให้ขวางการทำงานหลัก

  1. Ingest: ทันทีที่จบ Request ข้อมูลจะถูกยิงเข้า AWS SNS
  2. Buffer: กระจายข้อมูลต่อเข้าสู่ SQS Queues หลายตัวเพื่อรองรับ Load มหาศาล
  3. Orchestrate: ใช้เครื่องมือชื่อ Bento ในการจัดการ Stream ข้อมูล
  4. Storage: ปลายทางคือ ClickHouse Cloud พระเอกของงาน Data Analytics ที่อ่าน/เขียนข้อมูลปริมาณมากได้เร็วสุดๆ

4. Frontend & Infrastructure

  • Dashboard: สร้างด้วย Next.js และ React โดย Self-host บน AWS EKS เอง (ไม่ได้ใช้ Vercel สำหรับส่วนนี้)
  • Website & Docs: ส่วนหน้าบ้านใช้ Next.js และ Astro (สำหรับ Docs) โดย Deploy บน Vercel
  • DevOps Philosophy:
    • Container-First: ทีมพัฒนาทุกคนใช้ Devcontainers เพื่อให้ Environment เหมือนกันหมด
    • Local Simulation: ใช้ Orbstack (แทน Docker Desktop) และ Localstack จำลอง AWS Services บนเครื่องตัวเอง
    • Deployment: ใช้ Octopus Deploy โดยตั้งกฎเหล็กว่าต้องมี "Human Approval" ก่อนขึ้น Production เสมอ

บทเรียนจาก Arcjet Tech Stack

สิ่งที่น่าสนใจจากสถาปัตยกรรมของ Arcjet คือการเลือกเครื่องมือที่ "Right Tool for the Right Job" อย่างแท้จริง:

  1. Rust + Wasm: สำหรับ Logic ที่ต้องการความเร็วและพกพาไปได้ทุกที่
  2. Go + gRPC + Redis: สำหรับ Hot Path ที่ต้องตอบสนองใน 25ms เพื่อไม่ให้ User รอนาน
  3. ClickHouse + SQS: สำหรับ Cold Path ที่เน้นการรองรับข้อมูลมหาศาล

เป็น Case Study ที่ผสมผสานเทคโนโลยียุคใหม่ได้ลงตัวมากครับ ใครที่กำลังทำระบบ High-load ลองนำไอเดียการแยก Hot/Cold Path นี้ไปปรับใช้ดูได้ครับ!

sandwiched-developer-author
s
เขียนโดย

sirawich

อ่านต่อ

บทความที่เกี่ยวข้อง

TypeScript 7.0: จุดจบของ JS เขียน JS และรุ่งอรุณแห่ง Native Core
sandwiched-developer-author
s
sirawich
·ธ.ค. 16, 2025

TypeScript 7.0: จุดจบของ JS เขียน JS และรุ่งอรุณแห่ง Native Core

featured
sandwiched-developer-author
s
sirawich
·ธ.ค. 11, 2025

ONNX คืออะไร? เจาะลึกวิธีรัน AI บน Frontend แบบ "Local" ไม่ง้อ Cloud (ฉบับ Developer)

whats-new-in-lighthouse-13-cover-image
sandwiched-developer-author
s
sirawich
·พ.ย. 14, 2025

Lighthouse 13 มีอะไรใหม่

summarize-why-are-software-engineers-quitting-microservices-cover-image
sandwiched-developer-author
s
sirawich
·ต.ค. 25, 2025

สรุปวิดีโอ Why Are Software Engineers Quitting microservices ?

arktype-validator-cover-image
sandwiched-developer-author
s
sirawich
·ต.ค. 11, 2025

ArkType: เมื่อ TypeScript พูดภาษาของมันเอง

grab-migration-from-go-to-rust-cover-image
sandwiched-developer-author
s
sirawich
·ต.ค. 8, 2025

News: Grab ได้ทำการ migrate service บางส่วนจาก Go เป็น Rust

sandwiched-developer-get-to-know-normal-ui-cover
sandwiched-developer-author
s
sirawich
·ก.ย. 7, 2025

Normal UI – ทำให้เว็บแอปใช้ง่ายขึ้นโดยไม่ต้องเป็นดีไซเนอร์

react-submit-2024-topic-why-typescript-so-slow
sandwiched-developer-author
s
sirawich
·มิ.ย. 24, 2025

React Summit 2024: ทำไม TypeScript ถึงช้า

sandwiched-developer-golang-art-of-empty-world
sandwiched-developer-author
s
sirawich
·มิ.ย. 20, 2025

🕊️ Golang: ศิลปะแห่งความว่างเปล่าที่เปลี่ยนโลก

sandwiched-developer-go-ภาษาของผู้ไม่เร่งรีบ-แต่ไปถึงเส้นชัยก่อน
sandwiched-developer-author
s
sirawich
·มิ.ย. 3, 2025

🐢 Go: ภาษาของผู้ไม่เร่งรีบ แต่ไปถึงเส้นชัยก่อน