Back to Home

Hummingbird Swift: Guide for Backend Developers

The article provides a detailed guide to implementing Hummingbird for creating server applications on Swift. Key configuration aspects, comparison with Vapor, and development optimization methods are covered. The material is aimed at middle/senior developers.

Hummingbird on Swift: Complete Guide to Production Deployment
Advertisement 728x90

Hummingbird: A Practical Guide to Building Server Applications with Swift

Hummingbird is a modern, lightweight framework for backend development in Swift, combining high performance with minimal abstractions. Unlike traditional solutions, it's built on native async/await support, giving developers direct control over server logic. This article breaks down the key aspects of implementing the framework with a focus on practical examples.

Why Hummingbird Deserves Your Attention

Hummingbird is positioned as a tool for those who value architectural transparency. Unlike Vapor, the framework doesn't impose ready-made solutions for ORM or authentication, focusing on core HTTP server operations. This provides two key advantages:

  • Zero Overhead: No multi-layered abstractions means lower overhead when processing requests
  • Natural Asynchronicity: Built-in async/await support in Swift 5.5+ eliminates the need for callback hell

We've summarized the comparative characteristics in the table below:

Google AdInline article slot

| Criterion | Hummingbird | Vapor |

|------------------------|---------------------|-------------------|

| Dependency Size | 3 main packages | 15+ modules |

Google AdInline article slot

| Initialization | 120 ms | 450 ms |

| Horizontal Scaling | Native support | Requires tweaks |

| Entry Barrier | Medium | Low |

Google AdInline article slot

It's especially important that Hummingbird doesn't try to emulate outdated parallelism models—it leverages modern Swift tools out of the box. This is crucial for high-load projects where every micro-interaction impacts overall performance.

Creating a Production-Ready Project

The standard Hummingbird template provides a minimal working configuration. To get started, run:

git clone https://github.com/hummingbird-project/template
./template/configure.sh ProductionApp

It's important to understand the structure of the generated project. Key components:

  • ConfigReader — multi-level configuration system
  • Router — declarative router with middleware chains
  • ApplicationProtocol — entry point with lifecycle control

Let's look at implementing a basic endpoint with JSON handling:

router.post("/users") { request, context in
    guard let user = try? request.decode(User.self) else {
        return Response(status: .badRequest)
    }
    let id = try await Database.save(user)
    return Response(
        status: .created,
        headers: [.location: "/users/\(id)"]
    )
}

Key points:

  • Using decode instead of manual request body parsing
  • Built-in error handling via throw
  • Direct access to HTTP headers via typed enums

Configuration Management in Real-World Scenarios

Hummingbird implements an advanced configuration system with prioritized source handling. Parameter resolution order:

  • Command-line arguments
  • Environment variables
  • .env files
  • Default values in code

This allows flexible configuration for different environments. For example, for a staging environment:

swift run --port 8081 --log.level debug

In code, reading a parameter looks like this:

let port = reader.int(forKey: "port", default: 8080)
let logLevel = reader.string(
    forKey: "log.level",
    as: Logger.Level.self,
    default: .info
)

Note the safe type casting via generics—this prevents runtime type conversion errors.

Automating Development

To boost productivity, set up hot-reload. Watchexec restarts the server when .swift files change:

brew install watchexec
watchexec -e swift --restart "swift run"

Critical watchexec settings:

  • --restart — forces reload instead of sending a signal
  • -i — ignores temp files (e.g., .swiftpm)
  • --no-default-ignore — disables default ignore rules

Example optimized command:

watchexec --no-default-ignore -i .build -i .swiftpm -e swift --restart "swift run"

This cuts the edit-test cycle from 5-7 seconds to 1-2 seconds, which is crucial during active development.

Key Takeaways

  • Hummingbird requires understanding low-level HTTP concepts but compensates with top-tier performance
  • No built-in ORM means using specialized libraries (e.g., SwiftSQL)
  • Prioritized config sources simplify deployment across environments
  • Native async/await support eliminates the need for adapters in modern Swift apps
  • Watchexec becomes essential for comfortable development

— Editorial Team

Advertisement 728x90

Read Next