Skip to content
← All Skills

Fiber

Express-inspired Go web framework — zero allocation routing, high throughput, fasthttp-based

What I Can Do

  • สร้าง high-performance API ด้วย Fiber + fasthttp
  • Migrate จาก Express.js/Gin มา Fiber ได้ราบรื่น (API คล้าย Express)
  • Implement WebSocket, Server-Sent Events สำหรับ real-time features
  • ออกแบบ middleware chain สำหรับ production workloads
  • Optimize throughput สำหรับ high-traffic endpoints

Commands I Use Daily

bash
# install Fiber v2
go get github.com/gofiber/fiber/v2

# run server ตอน dev
go run ./cmd/server

# run tests
go test -v ./internal/handler/...

# benchmark (ใช้ hey หรือ wrk)
hey -n 10000 -c 100 http://localhost:3000/api/health

App & Routing Basics

app := fiber.New() สร้าง app instance — routing syntax คล้าย Express: app.Get("/users/:id", handler), app.Post("/users", handler) ใช้ path parameters (:id), optional params (:id?), wildcards (*)

Route Groups & Prefixes

api := app.Group("/api"), v1 := api.Group("/v1") — จัด routes เป็น hierarchy, apply middleware per group, แยก concerns ระหว่าง public/private/admin routes

Context (fiber.Ctx)

*fiber.Ctx คือ core — อ่าน request ด้วย c.Params("id"), c.Query("page"), c.Body(), เขียน response ด้วย c.JSON(), c.SendString(), c.Status(201).JSON() ต่างจาก Gin ตรงที่ Ctx ไม่ reuse ข้าม requests (pool-based)

Request Parsing & Body Parser

  • c.BodyParser(&struct) — parse JSON/XML/form body เข้า struct
  • c.Params("id") — path parameters
  • c.Query("page", "1") — query string with default value
  • c.Get("Authorization") — read headers
  • รองรับ multipart form data อัตโนมัติ

Validation

ใช้ go-playground/validator ร่วมกับ c.BodyParser — struct tags validate:"required,min=1" ตรวจ input, return structured error response เมื่อ validation fail

Middleware Basics

app.Use(middleware) — apply globally, group.Use() — apply per group, middleware เป็น function func(c *fiber.Ctx) error เรียก c.Next() ไป handler ถัดไป return error เพื่อ abort

Built-in Middleware

Fiber มี middleware พร้อมใช้:

  • logger.New() — request logging
  • recover.New() — recover จาก panic
  • cors.New() — CORS headers
  • limiter.New() — rate limiting
  • compress.New() — gzip/brotli compression
  • cache.New() — response caching

Custom Middleware

เขียน middleware pattern: func MyAuth() fiber.Handler { return func(c *fiber.Ctx) error { ... return c.Next() } } ใช้สำหรับ authentication, request ID injection, timing, custom logging

Error Handling

  • Return error จาก handler → Fiber จัดการด้วย default error handler
  • fiber.NewError(404, "not found") — สร้าง error พร้อม status code
  • Custom error handler: app := fiber.New(fiber.Config{ErrorHandler: customHandler}) centralized error handling

Static Files & Templates

  • app.Static("/", "./public") — serve static files
  • Template engines: html, pug, handlebars ผ่าน fiber.Config{Views: engine}
  • c.Render("index", data) — render template with data

Fasthttp Advantage

Fiber สร้างบน fasthttp แทน net/http — zero memory allocation สำหรับ hot paths, reuse buffers, เร็วกว่า net/http 5-10x ในบาง benchmarks ข้อเสีย: ไม่ compatible กับ net/http middleware ecosystem โดยตรง

Fiber vs Gin

  • Fiber — Express-like API, fasthttp-based, เร็วกว่าใน benchmarks, middleware ecosystem ของตัวเอง
  • Gin — net/http-based, ใหญ่กว่า community, compatible กับ standard library middleware
  • เลือก Fiber เมื่อ throughput สำคัญ, เลือก Gin เมื่อต้องการ ecosystem ที่ใหญ่กว่า

WebSocket

github.com/gofiber/websocket/v2 — upgrade HTTP connection เป็น WebSocket, app.Get("/ws", websocket.New(handler)) ใช้สำหรับ real-time features เช่น chat, live updates, trading data streams

Server-Sent Events (SSE)

ใช้ c.Context().SetBodyStreamWriter() สำหรับ streaming response — ส่ง events จาก server ไป client แบบ one-way, ง่ายกว่า WebSocket สำหรับ use cases เช่น notifications, live logs

JWT Authentication

ใช้ github.com/gofiber/jwt/v3 middleware — validate JWT token จาก Authorization header, extract claims, set ใน c.Locals("user") สำหรับ downstream handlers

Rate Limiting

limiter.New(limiter.Config{Max: 100, Expiration: 1 * time.Minute}) — จำกัด requests per window, configurable per IP/key, ใช้ memory store (default) หรือ Redis store สำหรับ distributed

Prefork Mode

app.Listen(":3000", fiber.Config{Prefork: true}) — spawn multiple processes (เหมือน Node.js cluster) ใช้ SO_REUSEPORT ให้แต่ละ process accept connections, เพิ่ม throughput บน multi-core machines

Hooks & Lifecycle

  • app.Hooks().OnListen(func() error { ... }) — run เมื่อ server start listening
  • app.Hooks().OnShutdown(func() error { ... }) — cleanup เมื่อ shutdown
  • ใช้จัดการ graceful shutdown, connection draining, resource cleanup

Testing

ใช้ app.Test(req) — ส่ง *http.Request เข้า app โดยไม่ต้อง start server, return *http.Response สำหรับ assert, เร็วมากเพราะ in-memory ไม่ผ่าน network

Performance Optimization

  • fiber.Config{Prefork: true} — multi-process mode
  • compress.New() — response compression
  • cache.New() — response caching per route
  • Tune ReadBufferSize, WriteBufferSize, Concurrency ใน config
  • ใช้ sync.Pool สำหรับ frequently allocated objects

ปัญหาที่เจอบ่อย & วิธีแก้

Ctx values หายหลัง handler จบ — fasthttp pool reuse

เก็บ c.Body() หรือ c.Params() ไว้ใช้ทีหลังแล้วได้ค่าผิดหรือ empty

สาเหตุ: Fiber สร้างบน fasthttp ที่ reuse request/response objects ผ่าน sync.Pool — ค่าที่ได้จาก c.Body(), c.Params(), c.Query() เป็น []byte ที่ชี้ไป buffer เดิม พอ request จบ buffer ถูก reuse ค่าจะเปลี่ยน

วิธีแก้:

  • copy ค่าทันทีที่ได้: body := make([]byte, len(c.Body())); copy(body, c.Body()) หรือใช้ string(c.Body())
  • ใช้ c.BodyParser(&struct) แทน c.Body() — parse เข้า struct จะ copy ให้อัตโนมัติ
  • ใช้ utils.CopyString(c.Params("id")) สำหรับ string values ที่ต้องเก็บไว้ใช้นอก handler

net/http middleware ใช้กับ Fiber ไม่ได้

Middleware จาก ecosystem ของ net/http/Gin เอามาใช้กับ Fiber ตรงๆ ไม่ได้

สาเหตุ: Fiber ใช้ fasthttp ไม่ใช่ net/http — interface ต่างกัน http.Handler vs fiber.Handler, request/response objects คนละ type

วิธีแก้:

  • ใช้ adaptor package: github.com/gofiber/adaptor/v2 แปลง http.Handlerfiber.Handler ด้วย adaptor.HTTPHandler(netHTTPHandler)
  • ตรวจว่า Fiber มี built-in middleware ทดแทนหรือไม่ (cors, limiter, compress มีครบ)
  • สำหรับ middleware ที่ซับซ้อน: เขียน Fiber version ใหม่อาจเร็วกว่า adapt เพราะใช้ fasthttp features ได้เต็มที่

BodyParser ไม่ parse — struct fields เป็น zero value

c.BodyParser(&req) ไม่ error แต่ struct fields ยังเป็น zero value ทั้งหมด

สาเหตุ: ลืมใส่ json:"field_name" struct tags, Content-Type header ไม่ตรง (ส่ง JSON แต่ไม่มี Content-Type: application/json), หรือ struct fields เป็น unexported (ตัวเล็กนำหน้า)

วิธีแก้:

  • ตรวจ struct tags: type Req struct { Name string \json:"name"` }` — ต้องมี json tag
  • ตรวจ Content-Type header ของ request — Fiber ใช้ Content-Type เลือก parser (JSON, XML, form)
  • ตรวจว่า struct fields เป็น exported (ตัวใหญ่นำหน้า)
  • ใช้ c.Body() debug ดู raw body ที่ได้รับจริง

Prefork mode กับ in-memory state ไม่ sync

ใช้ Prefork แล้ว state เช่น rate limit counter หรือ cache ไม่ตรงกันระหว่าง processes

สาเหตุ: Prefork spawn หลาย OS processes — แต่ละ process มี memory space แยกกัน in-memory store (map, sync.Map) ไม่ share ข้าม processes

วิธีแก้:

  • ใช้ external store แทน in-memory: Redis สำหรับ rate limiting, caching, session
  • limiter.New(limiter.Config{Storage: redisStore}) — ใช้ Redis store แทน memory store
  • ถ้าไม่ต้องการ shared state: ปิด Prefork แล้วใช้ goroutines (default) ซึ่ง share memory ได้

Error handler ไม่จับ panic

Panic ใน handler ทำ process crash แทนที่จะ return 500

สาเหตุ: ลืมใส่ recover middleware, หรือใส่ผิดลำดับ (ต้องอยู่ก่อน routes) — Fiber ไม่ recover panic by default ต่างจาก gin.Default() ที่มี recovery built-in

วิธีแก้:

  • ใส่ app.Use(recover.New()) ก่อน route definitions ทุกตัว
  • สำหรับ custom recovery: recover.New(recover.Config{EnableStackTrace: true}) เพื่อ log stack trace
  • เขียน custom error handler ใน fiber.Config{ErrorHandler: func(c *fiber.Ctx, err error) error { ... }} จัดการ error format รวมศูนย์

WebSocket connection ค้าง / memory leak

WebSocket connections สะสมจน server กิน memory เพิ่มขึ้นเรื่อยๆ

สาเหตุ: ไม่ handle connection close properly — client disconnect แต่ server ไม่ detect, ไม่มี ping/pong heartbeat, goroutine ที่อ่าน/เขียน WebSocket ไม่ถูก cleanup

วิธีแก้:

  • ตั้ง read/write deadline: ถ้าไม่มี activity ภายใน timeout ให้ close connection
  • ใช้ ping/pong: conn.SetPongHandler() + periodic ping เพื่อ detect dead connections
  • Track active connections ใน map + cleanup เมื่อ connection close
  • ใช้ defer conn.Close() ทุกครั้งที่ accept connection ใหม่

Related Skills

  • Go — ภาษาที่ Fiber สร้างขึ้นมา
  • Gin — alternative Go web framework ที่ community ใหญ่กว่า
  • GORM — ORM ที่ใช้คู่กับ Fiber เป็น data layer
  • Kafka — event-driven architecture คู่กับ Fiber API
  • Redis — caching layer สำหรับ Fiber services