Featured image of post Fiber: Blazing Fast Web Framework for Go Developers

Fiber: Blazing Fast Web Framework for Go Developers

An Express.js inspired web framework build on Fasthttp.

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:

  1. 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(), and app.Use().

  2. Lightning Fast Performance: Built on Fasthttp, Fiber delivers HTTP request handling that’s 2-5x faster than the standard net/http package, making it ideal for high-traffic applications.

  3. Middleware Ecosystem: With over 70 official middleware packages (authentication, CORS, compression, etc.), Fiber offers ready-to-use solutions for common web development tasks.

  4. Route Parameters and Groups: Supports complex routing patterns with named parameters (:id), wildcards (*), and route groups (api/v1), enabling clean and organized endpoint management.

  5. Request Parsing: Automatic parsing of JSON, form, and multipart requests with type-safe access through c.BodyParser(), eliminating manual validation boilerplate.

  6. Static File Serving: Built-in support for serving static files with customizable cache headers and directory listings.

  7. 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:

  1. fiber.New() initializes the app with optional configuration
  2. app.Use() applies middleware (here, logger for request logging)
  3. app.Get() defines GET routes:
    • Root route returns JSON
    • /user/:name captures URL parameters
    • /download/* matches any subpath
  4. Each route handler receives a fiber.Ctx context object for request/response manipulation

Expected Output:

  • http://localhost:3000/{"message":"Hello from Fiber!","status":"active"}
  • http://localhost:3000/user/johnUser: john
  • http://localhost:3000/download/file.zipDownloading: 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:

  1. Register user: POST /register with JSON body
  2. Login: POST /login to get JWT token
  3. 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:

  1. Connect to ws://localhost:3000/ws
  2. Send JSON messages: {"username":"user1","text":"Hello"}
  3. Receive messages with timestamps from all connected clients

Best Practices and Common Pitfalls

Best Practices:

  1. Route Organization: Use route groups (api/v1) for versioned APIs and separate modules for different functionalities.
  2. Middleware Ordering: Apply middleware in logical order (security → logging → business logic). Authentication should come before routes that require it.
  3. Error Handling: Implement custom error handlers and use fiber.Error for HTTP status codes. Always validate input before processing.
  4. Performance Tuning: For high-traffic applications, disable keep-alive and use connection pooling with fiber.New(fiber.Config{...}) settings.
  5. 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:

  1. Blocking Routes: Avoid long-running synchronous operations in route handlers. Use goroutines and channels for background tasks.
  2. Memory Leaks: Properly close database connections and release resources in defer statements, especially in WebSocket connections.
  3. Overusing Global State: Thread-safe global state can cause issues. Use dependency injection or context-scoped values instead.
  4. Ignoring Context Timeouts: Always respect context.WithTimeout() for operations like database queries.
  5. 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 pprof by adding app.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.

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy