<!--
{
  "documentType" : "article",
  "framework" : "Event",
  "identifier" : "/documentation/Event/SwiftEventVsSwiftNIOVsHummingbirdVsNetworkFramework",
  "metadataVersion" : "0.1.0",
  "role" : "article",
  "title" : "swift-event vs SwiftNIO vs Hummingbird vs Network.framework"
}
-->

# swift-event vs SwiftNIO vs Hummingbird vs Network.framework

A decision-tree comparison of the four common Swift networking choices, written from inside swift-event but trying not to mark its own homework.

## Overview

Four options keep coming up in “what should I use for networking in Swift?” forum threads:

- **``doc://Event/documentation/Event``** — this package. Thin async/await wrapper (``doc://Event/documentation/Event/Socket``, ``doc://Event/documentation/Event/ServerSocket``, ``doc://Event/documentation/Event/EventLoop``) over libevent’s kqueue/epoll multiplexer. Plain TCP, no built-in TLS/HTTP/WebSocket.
- **[SwiftNIO](https://github.com/apple/swift-nio)** — Apple’s full event-loop networking stack. Channel pipelines, protocol handlers, an ecosystem of modules (HTTP/1, HTTP/2, WebSocket, TLS).
- **[Hummingbird](https://github.com/hummingbird-project/hummingbird)** — server-side Swift HTTP framework built on SwiftNIO. Routing, middleware, async/await-native APIs above NIO’s channel layer.
- **[Network.framework](https://developer.apple.com/documentation/network)** — Apple’s modern (2018) networking framework, callback-shaped, deeply integrated with the system network stack on Apple platforms only.

This article is a decision tree, not a tier list. Each is the right answer for a specific shape of problem.

### Decision tree

**Pick the framework by question shape, not feature checklist:** HTTP server → Hummingbird; Apple-only with TLS → Network.framework; plain TCP with async/await → [`Event`](/documentation/Event); 10k+ concurrent connections → SwiftNIO; embedding a libevent-based C library → [`Event`](/documentation/Event)’s `libevent` product. The five-question tree below disambiguates the edges.

1. **Are you building an HTTP server (REST, GraphQL, WebSocket)?**
- Yes → **Hummingbird** if you want async/await-first ergonomics. **SwiftNIO** + `swift-nio-http` if you want the lowest-level protocol control or you’re integrating with existing NIO-based code.
- No → continue.
1. **Are you Apple-platform-only and need TLS, multipath, or system-managed routing?**
- Yes → **Network.framework**. The `NWConnection` callback shape is the price you pay for the platform integration.
- No → continue.
1. **Are you doing plain TCP and you want async/await with a small dependency footprint?**
- Yes → **``doc://Event/documentation/Event``** — see ``doc://Event/documentation/Event/Socket/connect(to:port:loop:timeout:)`` and ``doc://Event/documentation/Event/Socket/listen(port:backlog:loop:)``. If you also need cross-platform reach to Linux, this is the lane.
- No → continue.
1. **Do you need extreme connection scale (10k+ concurrent connections, multi-core saturation)?**
- Yes → **SwiftNIO** with `MultiThreadedEventLoopGroup`. The thread-fanout model is what NIO is built for.
- No → **``doc://Event/documentation/Event``** is likely fine — it runs a single ``doc://Event/documentation/Event/EventLoop`` per scope.
1. **Are you embedding a C library that already speaks libevent (Tor, libssh, custom C code)?**
- Yes → **``doc://Event/documentation/Event``** ships the raw `libevent` C product as a re-exportable SwiftPM target. See <doc://Event/documentation/Event/ChoosingLibeventVsEvent> for the product-selection rationale and <doc://Event/documentation/Event/EmbeddingCLibrariesInSwiftPM> for the module-map pattern.

> Note: This decision tree shortcuts when the answer to question 1 is “yes” (HTTP server). Hummingbird and SwiftNIO + `swift-nio-http` are the only practical Swift choices for production HTTP servers — ``doc://Event/documentation/Event`` does not wrap HTTP and we have no plan to. Question 3 onward is for non-HTTP cases.

### Side-by-side comparison table

|Capability                            |``doc://Event/documentation/Event``                                     |SwiftNIO                                    |Hummingbird             |Network.framework              |
|--------------------------------------|------------------------------------------------------------------------|--------------------------------------------|------------------------|-------------------------------|
|Async/await native                    |✅                                                                       |Partial (NIOAsyncChannel bridges)           |✅                       |❌ (callback-only)              |
|Plain TCP client/server               |✅                                                                       |✅                                           |(via NIO)               |✅                              |
|HTTP/1 server                         |❌                                                                       |✅ (`swift-nio-http1`)                       |✅                       |❌                              |
|HTTP/2 server                         |❌                                                                       |✅ (`swift-nio-http2`)                       |✅                       |❌                              |
|WebSocket                             |❌                                                                       |✅ (`swift-nio-websocket`)                   |✅                       |Partial (`NWWebSocket`)        |
|TLS                                   |❌                                                                       |✅ (`swift-nio-ssl`)                         |✅                       |✅ (built-in)                   |
|UDP                                   |❌                                                                       |✅                                           |(server-focused)        |✅                              |
|Unix-domain sockets                   |❌                                                                       |✅                                           |(via NIO)               |❌                              |
|Linux support                         |✅                                                                       |✅                                           |✅                       |❌ (Apple-only)                 |
|iOS support                           |✅                                                                       |✅                                           |✅ (NIOTransportServices)|✅                              |
|Threading model                       |Single loop, single owner per scope                                     |`MultiThreadedEventLoopGroup` (configurable)|NIO’s ELG               |System-managed                 |
|Backpressure                          |Manual (planned)                                                        |Built-in via channel pipeline               |Built-in via NIO        |Built-in via NWConnection state|
|Direct C-library embedding            |✅ (libevent product)                                                    |❌                                           |❌                       |❌                              |
|Cancellation propagation              |Partial (see <doc://Event/documentation/Event/ProductionConsiderations>)|Partial (NIOAsyncChannel known issues)      |✅ via async/await       |N/A (callback model)           |
|Pre-1.0 status                        |✅ (0.x today)                                                           |❌ (stable, 2.x)                             |❌ (stable, 2.x)         |❌ (stable since iOS 12)        |
|Approximate code size to “echo server”|~10 lines                                                               |~50 lines (channel pipeline)                |~10 lines               |~30 lines (callback bridging)  |

### Code shape comparison: an echo server in each

The same problem — accept TCP connections and echo back received bytes — takes ~10 lines in [`Event`](/documentation/Event), ~50 lines in SwiftNIO, ~10 lines in Hummingbird (HTTP, not raw TCP), and ~30 lines in Network.framework. The line counts reflect the abstraction depth each library imposes, not the underlying capability.

**``doc://Event/documentation/Event``** — full compiled snippet using [`listen(port:backlog:loop:)`](/documentation/Event/Socket/listen(port:backlog:loop:)), [`connections`](/documentation/Event/ServerSocket/connections), [`read(maxBytes:timeout:)`](/documentation/Event/Socket/read(maxBytes:timeout:)), and [`write(_:timeout:)`](/documentation/Event/Socket/write(_:timeout:)):

```swift

```

**SwiftNIO** (using NIOAsyncChannel, the post-2024 ergonomic shape):

```swift
let server = try await ServerBootstrap(group: NIOSingletons.posixEventLoopGroup)
    .childChannelOption(.socketOption(.so_reuseaddr), value: 1)
    .bind(host: "0.0.0.0", port: 8080) { channel in
        channel.eventLoop.makeCompletedFuture {
            try NIOAsyncChannel<ByteBuffer, ByteBuffer>(wrappingChannelSynchronously: channel)
        }
    }

try await withThrowingDiscardingTaskGroup { group in
    try await server.executeThenClose { connections in
        for try await connection in connections {
            group.addTask {
                try await connection.executeThenClose { inbound, outbound in
                    for try await chunk in inbound {
                        try await outbound.write(chunk)
                    }
                }
            }
        }
    }
}
```

**Hummingbird** (HTTP, not raw TCP — Hummingbird’s domain is HTTP so the equivalent is “echo POST body”):

```swift
let router = Router()
router.post("/") { request, _ in
    let body = try await request.body.collect(upTo: .max)
    return Response(status: .ok, body: ResponseBody(byteBuffer: body))
}
let app = Application(router: router, configuration: .init(address: .hostname("0.0.0.0", port: 8080)))
try await app.runService()
```

**Network.framework:**

```swift
let listener = try NWListener(using: .tcp, on: 8080)
listener.newConnectionHandler = { connection in
    connection.start(queue: .global())
    connection.receive(minimumIncompleteLength: 1, maximumLength: 4096) { data, _, _, _ in
        guard let data = data else { return }
        connection.send(content: data, completion: .contentProcessed { _ in
            connection.cancel()
        })
    }
}
listener.start(queue: .global())
RunLoop.main.run()
```

### Choosing for specific scenarios

**“I’m writing an iOS app that needs to talk plain TCP to my server.”** → [`Event`](/documentation/Event) via [`connect(to:port:loop:timeout:)`](/documentation/Event/Socket/connect(to:port:loop:timeout:)). See [Async TCP Client for iOS in Swift](/documentation/Event/TCPClientForIOSWithSwift). `Network.framework` works too but the callback shape is awkward in modern Swift.

**“I’m writing a Vapor-style web service.”** → Hummingbird (or Vapor itself if you want the full ORM/template ecosystem). Both build on NIO under the hood.

**“I need to handle 50k concurrent WebSocket clients.”** → SwiftNIO directly, with `MultiThreadedEventLoopGroup` sized to your core count, plus `swift-nio-websocket`.

**“I’m porting a C codebase that uses libevent (Tor, libssh, custom binary protocol library) to a Swift package.”** → [`Event`](/documentation/Event). The package’s `libevent` C product is consumable by other Swift packages exactly for this case. See [Choosing Between Event and libevent](/documentation/Event/ChoosingLibeventVsEvent) and [Embedding a C Library in Swift Package Manager](/documentation/Event/EmbeddingCLibrariesInSwiftPM).

**“I need TLS but don’t want to depend on swift-nio-ssl.”** → `Network.framework` on Apple platforms (TLS is built in). On Linux, you currently have to bring TLS yourself; [`Event`](/documentation/Event) does not wrap TLS today.

**“I want to write an MQTT broker / Redis-compatible server / custom binary-protocol daemon.”** → Almost certainly [`Event`](/documentation/Event) is enough, especially if the protocol is length-prefixed binary (see [Handling Partial Reads in Swift TCP Sockets: Length-Prefix and Delimiter Framing](/documentation/Event/PartialReadsAndMessageFraming)). Reach for SwiftNIO if the protocol is async-message-multiplexed in ways that benefit from a channel-pipeline architecture.

### Honest disclosures

> Important: This article is published in ``doc://Event/documentation/Event``’s own documentation. SwiftNIO and Hummingbird are mature, production-grade libraries with years of real deployment behind them; ``doc://Event/documentation/Event`` is pre-1.0 and ships a deliberately narrow surface. The decision tree above tries to recommend the right tool for the job rather than the home team — but you should weigh the source.

Two biases worth naming explicitly:

1. **Recency bias.** ``doc://Event/documentation/Event`` is pre-1.0; SwiftNIO and Hummingbird are mature stable libraries with years of production use. The capability gaps in the comparison table are not abstract — they reflect features ``doc://Event/documentation/Event`` has deliberately not yet shipped, and “we don’t have your bug” can become “we don’t have your feature” quickly. See <doc://Event/documentation/Event/ProductionConsiderations> for the full caveats list (and ``doc://Event/documentation/Event/SocketError`` for the error surface).
1. **Scope bias.** Comparing a thin libevent wrapper (``doc://Event/documentation/Event/Socket`` / ``doc://Event/documentation/Event/ServerSocket`` / ``doc://Event/documentation/Event/EventLoop``) to a full HTTP framework (Hummingbird) is comparing different layers. The decision tree above tries to surface this — the right comparison for “what HTTP server should I use” is Hummingbird vs Vapor, not Hummingbird vs ``doc://Event/documentation/Event``.

For the libevent vs [`Event`](/documentation/Event) choice specifically (when to drop down from the Swift API to the raw C product), see [Choosing Between Event and libevent](/documentation/Event/ChoosingLibeventVsEvent).

## See Also

[Choosing Between Event and libevent](/documentation/Event/ChoosingLibeventVsEvent)

This package ships two library products — which one should you link? This article covers the decision boundary, the canonical consumer example (`swift-tor`), and the stability guarantees that differ between the idiomatic Swift API and the raw C bindings.

[Async TCP Client for iOS in Swift](/documentation/Event/TCPClientForIOSWithSwift)

A working TCP client that compiles for iOS (and iPadOS, tvOS, visionOS), with the simulator-localhost gotchas explicit and the `NWConnection` callback dance avoided.

[How to Write an Async TCP Server in Swift](/documentation/Event/AsyncTCPServerInSwift)

A complete async TCP server in Swift 6, end-to-end — bind, listen, accept, per-connection handler tasks, graceful close — without channel pipelines or `EventLoopFuture` plumbing.

[Embedding a C Library in Swift Package Manager](/documentation/Event/EmbeddingCLibrariesInSwiftPM)

How to make a C library consumable from Swift Package Manager — using libevent and [`Event`](/documentation/Event) as the worked example, with the module-map and product-re-export patterns extracted for your own ports.

[Production Considerations](/documentation/Event/ProductionConsiderations)

Pre-1.0 status, the concurrency model, resource-ownership rules, and the list of capabilities not yet shipping in `Event`.

[`Event`](/documentation/Event)

Async TCP sockets and event-loop primitives for Swift on top of `kqueue` (Apple platforms) or `epoll` (Linux), backed by a vendored build of libevent.

[`EventLoop`](/documentation/Event/EventLoop)

A libevent-backed event loop owning an `event_base` for async I/O dispatch.

[`Socket`](/documentation/Event/Socket)

An async non-blocking TCP socket backed by libevent.

[`ServerSocket`](/documentation/Event/ServerSocket)

A listening TCP server socket built on a non-blocking file descriptor and an [`EventLoop`](/documentation/Event/EventLoop).

[`SocketError`](/documentation/Event/SocketError)

An error surfaced by [`SocketAddress`](/documentation/Event/SocketAddress), [`Socket`](/documentation/Event/Socket), and [`ServerSocket`](/documentation/Event/ServerSocket) operations.

  [SwiftNIO](https://github.com/apple/swift-nio)

  [Hummingbird](https://github.com/hummingbird-project/hummingbird)

  [Network.framework](https://developer.apple.com/documentation/network)

