Introduction
In the ever-evolving landscape of web development, finding a framework that balances performance with developer experience is crucial. Enter Fiber, a Go web framework inspired by Express.js, built on top of the high-performance Fasthttp engine. With over 39,300 stars on GitHub, Fiber has emerged as a top choice for Go developers seeking rapid development without sacrificing speed. Its intuitive API, middleware ecosystem, and lightweight design make it ideal for building everything from microservices to full-stack applications. Fiber solves common Go web development challenges by providing a familiar syntax for JavaScript developers while leveraging Go’s concurrency model. It’s particularly well-suited for API development, real-time applications, and systems requiring high throughput. Whether you’re migrating from Node.js or building a new Go service, Fiber offers the sweet spot between raw performance and developer productivity.
Key Features
Fiber distinguishes itself through several powerful features that streamline web development in Go:
-
Express.js-inspired Syntax: Fiber provides a familiar routing and middleware pattern for developers coming from Node.js, drastically reducing the learning curve. This includes intuitive methods like
app.Get(),app.Post(), andapp.Use(). -
Lightning Fast Performance: Built on Fasthttp, Fiber delivers HTTP request handling that’s 2-5x faster than the standard
net/httppackage, making it ideal for high-traffic applications. -
Middleware Ecosystem: With over 70 official middleware packages (authentication, CORS, compression, etc.), Fiber offers ready-to-use solutions for common web development tasks.
-
Route Parameters and Groups: Supports complex routing patterns with named parameters (
:id), wildcards (*), and route groups (api/v1), enabling clean and organized endpoint management. -
Request Parsing: Automatic parsing of JSON, form, and multipart requests with type-safe access through
c.BodyParser(), eliminating manual validation boilerplate. -
Static File Serving: Built-in support for serving static files with customizable cache headers and directory listings.
-
WebSockets Support: Native WebSocket implementation for real-time applications, including connection management and message broadcasting.
Compared to standard Go, Fiber reduces code complexity while maintaining performance. For instance, a simple HTTP handler in net/http requires manual request parsing and response writing, whereas Fiber abstracts these details through its context object (c).
Installation and Setup
Getting started with Fiber is straightforward:
1go get github.com/gofiber/fiber/v2
Fiber requires Go 1.18+ and has no external dependencies beyond the standard library. To verify installation:
1package main
2
3import (
4 "fmt"
5 "github.com/gofiber/fiber/v2"
6)
7
8func main() {
9 app := fiber.New()
10 app.Get("/", func(c *fiber.Ctx) error {
11 return c.SendString("Fiber is installed!")
12 })
13 fmt.Println("Server running at http://localhost:3000")
14 app.Listen(":3000")
15}
Run with go run main.go and access http://localhost:3000 to see “Fiber is installed!”.
Basic Usage
Fiber’s minimal API makes creating web services intuitive. Here’s a breakdown of a basic application:
1package main
2
3import (
4 "github.com/gofiber/fiber/v2"
5 "github.com/gofiber/fiber/v2/middleware/logger"
6)
7
8func main() {
9 // Initialize Fiber app with custom config
10 app := fiber.New(fiber.Config{
11 // Enable strict routing (404 for unknown routes)
12 Strict: true,
13 // Server header
14 ServerHeader: "Fiber",
15 })
16
17 // Add global middleware
18 app.Use(logger.New())
19
20 // Define routes
21 app.Get("/", func(c *fiber.Ctx) error {
22 return c.JSON(map[string]string{
23 "message": "Hello from Fiber!",
24 "status": "active",
25 })
26 })
27
28 app.Get("/user/:name", func(c *fiber.Ctx) error {
29 name := c.Params("name")
30 return c.SendString(`User: ` + name)
31 })
32
33 // Wildcard route
34 app.Get("/download/*", func(c *fiber.Ctx) error {
35 return c.SendString("Downloading: " + c.Params("*"))
36 })
37
38 // Start server
39 app.Listen(":3000")
40}
Code Explanation:
fiber.New()initializes the app with optional configurationapp.Use()applies middleware (here, logger for request logging)app.Get()defines GET routes:- Root route returns JSON
/user/:namecaptures URL parameters/download/*matches any subpath
- Each route handler receives a
fiber.Ctxcontext object for request/response manipulation
Expected Output:
http://localhost:3000/→{"message":"Hello from Fiber!","status":"active"}http://localhost:3000/user/john→User: johnhttp://localhost:3000/download/file.zip→Downloading: file.zip
Real-World Examples
Example 1: REST API with JWT Authentication
This example demonstrates a production-ready API with authentication, validation, and database integration:
1package main
2
3import (
4 "github.com/gofiber/fiber/v2"
5 "github.com/gofiber/fiber/v2/middleware/cors"
6 "github.com/gofiber/fiber/v2/middleware/jwt"
7 "github.com/gofiber/fiber/v2/middleware/logger"
8 "github.com/gofiber/fiber/v2/middleware/recover"
9 "github.com/valyala/fasthttp"
10 "gorm.io/driver/sqlite"
11 "gorm.io/gorm"
12 "time"
13)
14
15// User model
16type User struct {
17 gorm.Model
18 Username string `json:"username" validate:"required,min=3,max=32"`
19 Password string `json:"password" validate:"required,min=6"`
20 Email string `json:"email" validate:"required,email"`
21}
22
23// Login request
24type LoginRequest struct {
25 Username string `json:"username" validate:"required"`
26 Password string `json:"password" validate:"required"`
27}
28
29// Product model
30type Product struct {
31 gorm.Model
32 Name string `json:"name" validate:"required"`
33 Price float64 `json:"price" validate:"required,gte=0"`
34 Description string `json:"description"`
35}
36
37func main() {
38 // Initialize database
39 db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
40 if err != nil {
41 panic("Failed to connect to database")
42 }
43 db.AutoMigrate(&User{}, &Product{})
44
45 // Fiber app setup
46 app := fiber.New(fiber.Config{
47 // Custom error handling
48 ErrorHandler: func(c *fiber.Ctx, err error) error {
49 code := fiber.StatusInternalServerError
50 if e, ok := err.(*fiber.Error); ok {
51 code = e.Code
52 }
53 return c.Status(code).JSON(fiber.Map{
54 "error": err.Error(),
55 })
56 },
57 })
58
59 // Middleware
60 app.Use(recover.New())
61 app.Use(cors.New())
62 app.Use(logger.New())
63
64 // JWT Middleware
65 jwtMiddleware := jwt.New(jwt.Config{
66 SigningKey: []byte("secret"),
67 ContextKey: "user",
68 Claims: jwt.MapClaims{},
69 TokenLookup: "header:Authorization,cookie:jwt",
70 SigningMethod: "HS256",
71 })
72
73 // Public routes
74 app.Post("/register", func(c *fiber.Ctx) error {
75 var user User
76 if err := c.BodyParser(&user); err != nil {
77 return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
78 }
79
80 // Hash password (in production use bcrypt/scrypt)
81 user.Password = "hashed_" + user.Password
82
83 if err := db.Create(&user).Error; err != nil {
84 return fiber.NewError(fiber.StatusInternalServerError, "Registration failed")
85 }
86
87 return c.Status(fiber.StatusCreated).JSON(user)
88 })
89
90 app.Post("/login", func(c *fiber.Ctx) error {
91 var req LoginRequest
92 if err := c.BodyParser(&req); err != nil {
93 return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
94 }
95
96 var user User
97 if err := db.Where("username = ?", req.Username).First(&user).Error; err != nil {
98 return fiber.NewError(fiber.StatusUnauthorized, "Invalid credentials")
99 }
100
101 // Compare hashed passwords (in production use bcrypt/scrypt)
102 if "hashed_"+req.Password != user.Password {
103 return fiber.NewError(fiber.StatusUnauthorized, "Invalid credentials")
104 }
105
106 // Generate JWT
107 token := jwt.Sign(jwt.MapClaims{
108 "user_id": user.ID,
109 "exp": time.Now().Add(time.Hour * 24).Unix(),
110 })
111
112 return c.JSON(fiber.Map{"token": token})
113 })
114
115 // Protected routes
116 api := app.Group("/api", jwtMiddleware)
117 api.Get("/profile", func(c *fiber.Ctx) error {
118 user := c.Locals("user").(jwt.MapClaims)
119 var u User
120 db.First(&u, user["user_id"])
121 return c.JSON(u)
122 })
123
124 api.Get("/products", func(c *fiber.Ctx) error {
125 var products []Product
126 db.Find(&products)
127 return c.JSON(products)
128 })
129
130 api.Post("/products", func(c *fiber.Ctx) error {
131 var product Product
132 if err := c.BodyParser(&product); err != nil {
133 return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
134 }
135
136 if err := db.Create(&product).Error; err != nil {
137 return fiber.NewError(fiber.StatusInternalServerError, "Product creation failed")
138 }
139
140 return c.Status(fiber.StatusCreated).JSON(product)
141 })
142
143 app.Listen(":3000")
144}
Features Demonstrated:
- JWT authentication with protected routes
- Database integration (SQLite with GORM)
- Input validation
- Custom error handling
- CORS and security middleware
- RESTful API endpoints for user management and products
Usage:
- Register user:
POST /registerwith JSON body - Login:
POST /loginto get JWT token - Use token in
Authorization: Bearer <token>header for protected routes
Example 2: Real-time WebSocket Chat Application
This WebSocket example shows real-time communication with connection management:
1package main
2
3import (
4 "github.com/gofiber/fiber/v2"
5 "github.com/gofiber/fiber/v2/middleware/cors"
6 "github.com/gofiber/fiber/v2/middleware/logger"
7 "github.com/gofiber/websocket/v2"
8 "sync"
9 "time"
10)
11
12// Message structure
13type Message struct {
14 Username string `json:"username"`
15 Text string `json:"text"`
16 Time string `json:"time"`
17}
18
19// Hub manages WebSocket connections
20type Hub struct {
21 clients map[*websocket.Conn]bool
22 broadcast chan Message
23 register chan *websocket.Conn
24 unregister chan *websocket.Conn
25 mutex sync.Mutex
26}
27
28func newHub() *Hub {
29 return &Hub{
30 broadcast: make(chan Message),
31 register: make(chan *websocket.Conn),
32 unregister: make(chan *websocket.Conn),
33 clients: make(map[*websocket.Conn]bool),
34 }
35}
36
37func (h *Hub) run() {
38 for {
39 select {
40 case conn := <-h.register:
41 h.mutex.Lock()
42 h.clients[conn] = true
43 h.mutex.Unlock()
44 conn.WriteJSON(Message{Text: "Welcome to the chat!"})
45
46 case conn := <-h.unregister:
47 h.mutex.Lock()
48 if _, ok := h.clients[conn]; ok {
49 delete(h.clients, conn)
50 conn.Close()
51 }
52 h.mutex.Unlock()
53
54 case message := <-h.broadcast:
55 h.mutex.Lock()
56 for conn := range h.clients {
57 if err := conn.WriteJSON(message); err != nil {
58 conn.Close()
59 delete(h.clients, conn)
60 }
61 }
62 h.mutex.Unlock()
63 }
64 }
65}
66
67func main() {
68 hub := newHub()
69 go hub.run()
70
71 app := fiber.New()
72 app.Use(cors.New())
73 app.Use(logger.New())
74
75 // WebSocket endpoint
76 app.Get("/ws", websocket.New(func(c *websocket.Conn) {
77 defer func() {
78 hub.unregister <- c
79 }()
80
81 hub.register <- c
82
83 for {
84 var message Message
85 if err := c.ReadJSON(&message); err != nil {
86 if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseNormalClosure) {
87 println("read error:", err.Error())
88 }
89 break
90 }
91 message.Time = time.Now().Format("2006-01-02 15:04:05")
92 hub.broadcast <- message
93 }
94 }))
95
96 // HTTP endpoint for health check
97 app.Get("/health", func(c *fiber.Ctx) error {
98 return c.SendStatus(fiber.StatusOK)
99 })
100
101 app.Listen(":3000")
102}
Features Demonstrated:
- WebSocket connection management
- Broadcast messaging to all connected clients
- Connection lifecycle handling (join/leave events)
- Real-time message timestamping
- Health check endpoint for load balancers
Usage:
- Connect to
ws://localhost:3000/ws - Send JSON messages:
{"username":"user1","text":"Hello"} - Receive messages with timestamps from all connected clients
Best Practices and Common Pitfalls
Best Practices:
- Route Organization: Use route groups (
api/v1) for versioned APIs and separate modules for different functionalities. - Middleware Ordering: Apply middleware in logical order (security → logging → business logic). Authentication should come before routes that require it.
- Error Handling: Implement custom error handlers and use fiber.Error for HTTP status codes. Always validate input before processing.
- Performance Tuning: For high-traffic applications, disable keep-alive and use connection pooling with
fiber.New(fiber.Config{...})settings. - Security: Always use HTTPS, implement rate limiting, and validate/sanitize all user input. For JWT, store tokens securely and use short expiration times.
Common Pitfalls:
- Blocking Routes: Avoid long-running synchronous operations in route handlers. Use goroutines and channels for background tasks.
- Memory Leaks: Properly close database connections and release resources in defer statements, especially in WebSocket connections.
- Overusing Global State: Thread-safe global state can cause issues. Use dependency injection or context-scoped values instead.
- Ignoring Context Timeouts: Always respect
context.WithTimeout()for operations like database queries. - Neglecting Security Headers: Use middleware to set security headers (Content-Security-Policy, X-Frame-Options, etc.).
Debugging Tips:
- Enable verbose logging with
logger.New(logger.Config{Output: os.Stdout}) - Use
c.Status(fiber.StatusInternalServerError).SendString(err.Error())in development for raw errors - Profile with
pprofby addingapp.Use(pprof.New())middleware
Conclusion
Fiber bridges the gap between Go’s performance and developer-friendly web frameworks, offering the best of both worlds. Its Express.js-inspired syntax makes it accessible while maintaining Go’s efficiency. With robust middleware, WebSocket support, and performance optimizations, Fiber is ideal for building modern web applications, APIs, and real-time systems. Whether you’re building microservices, full-stack applications, or high-traffic APIs, Fiber provides the tools to develop rapidly without compromising on performance. For more information, visit the official GitHub repository.