# Designing an HTTP Server API for Swift

**URL:** <https://forums.swift.org/t/designing-an-http-server-api-for-swift/85255>\
**Category:** Discussion\
**Tags:** http, server, swift-nio\
**Created:** [March 10, 2026, 3:31pm UTC](https://forums.swift.org/t/designing-an-http-server-api-for-swift/85255 "2026-03-10T15:31:30Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![guscairo](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/guscairo/32/39367_2.png) [@guscairo](https://forums.swift.org/u/guscairo)\
**Post date:** [March 10, 2026, 3:31pm UTC](https://forums.swift.org/t/designing-an-http-server-api-for-swift/85255/1 "2026-03-10T15:31:30Z")

</div>

Swift is becoming increasingly popular for server-side development, thanks to characteristics such as performance, safety, and developer productivity. At Apple, we’re increasingly writing new services in Swift and are therefore continuing to invest in improving its approachability for developing server-side applications. As a part of the ongoing work in [the proposed Swift networking vision](https://forums.swift.org/t/prospective-vision-networking/85235), we invite your participation as we work together to make Swift the best language for all networking use cases.

Existing frameworks provide solutions for building web applications, but they have opted to build their own low-level HTTP server implementation. This leads to a few issues:

- Duplicated implementations using the same building blocks (i.e. SwiftNIO), each with potentially different bugs, security or performance issues to deal with.
- Lack of unified currency types or abstractions, making it hard to share code across implementations.
- Some implementations lack structured concurrency support, forcing developers to use awkward adapters to bridge future- or callback-based APIs into async/await code.
- Bidirectional streaming support is inconsistent across implementations, particularly around HTTP trailers and request lifecycle management. This creates challenges for features that need visibility into the full request lifetime, such as distributed tracing via middleware or interceptors.
- Applications with simple networking needs currently face an awkward choice: use a full-featured framework like Vapor and accept its large dependency footprint, or work directly with SwiftNIO's low-level APIs. An intermediate layer would fill this gap, offering straightforward networking capabilities with minimal dependencies and appropriate abstraction.

An ideal solution would be to provide a low-level HTTP server that addresses these problems by providing a structured, concurrency-first approach that other frameworks can build upon, with full bidirectional streaming support, structured resource management, and safe APIs. Today we’re sharing an API and prototype implementation that demonstrates early progress towards this goal.

## Goals

We’ve got two main, high-level goals as part of this effort:

- Provide an abstract API interface, to be used by users who may want to build on top of the HTTP Server in an implementation-agnostic way (primarily library developers).
- Provide a high-performance concrete implementation of this interface based on SwiftNIO that can be used out-of-the-box.

For both pieces, we want full support for structured concurrency and resource management. This would enable in turn support for middlewares and bidirectional streaming, including trailers. This also would include the ability to capture the whole lifecycle of a streaming request and response (including their trailers), for things like tracing interceptors.

For the abstract interface in particular, our main goal is to provide an API that makes it hard for users to make mistakes, and uses ecosystem-wide currency types (such as `swift-http-types`).

For the concrete NIO implementation, we have a few more specific goals:

- HTTP/1.1, HTTP/2 and HTTP/3 support, with protocol negotiation, (m)TLS and certificate rotation.
- Support for graceful shutdown.
- APIs for connection management configuration (maximum number of connections, idle timeout, etc).
- Backpressure support:
  - On the number of requests a client can make
  - When reading from request bodies
  - When writing response bodies

_Note: there is an `HTTPClient` counterpart to this project that you can find linked at the bottom of this post._

## Proposal

_This API is still in its infancy and everyone is very much encouraged to provide feedback to make it the best it can be._

As we mentioned, this project has two parts: the abstract interface made up of several protocols that will allow greater flexibility for developers to build on top of HTTP server abstractions without being tied to any specific networking stack; and a concrete implementation of these protocols, backed by SwiftNIO.

### Abstract interface

#### HTTPServer

An abstract `HTTPServer` protocol that defines a single `serve(handler:)` method. Concrete types conforming to this protocol will provide this single, long-running method that will handle all incoming requests.

The protocol itself is straightforward:

```swift
public protocol HTTPServer: Sendable, ~Copyable, ~Escapable {
    associatedtype RequestConcludingReader: ConcludingAsyncReader
    associatedtype ResponseConcludingWriter: ConcludingAsyncWriter

    func serve(handler: some HTTPServerRequestHandler<RequestConcludingReader, ResponseConcludingWriter>) async throws
}

```

The protocol is marked as `~Copyable` and `~Escapable` to support modern Swift ownership semantics, ensuring efficient resource management. The single `serve(handler:)` method takes a request handler and runs indefinitely, processing all incoming HTTP connections.

To use an `HTTPServer`, you create a handler that conforms to `HTTPServerRequestHandler` and pass it to the server's `serve` method:

```swift
struct EchoHandler: HTTPServerRequestHandler {
    func handle(
        request: HTTPRequest,
        requestContext: HTTPRequestContext,
        requestBodyAndTrailers: consuming sending HTTPRequestConcludingAsyncReader,
        responseSender: consuming sending HTTPResponseSender<HTTPResponseConcludingAsyncWriter>
    ) async throws {
        let response = HTTPResponse(status: .ok)
        let writer = try await responseSender.send(response)
    }
}

```

We will dive deeper into the request handler below. Once you have your handler, you instantiate a concrete server implementation and start it:

```swift
let server = ... // create a concrete HTTPServer instance
try await server.serve(handler: EchoHandler())

```

This design keeps the server protocol minimal while delegating all request-handling logic to the handler, allowing for clean separation of concerns.

#### HTTPServerRequestHandler

The `handler` is an `HTTPServerRequestHandler`: a protocol that defines how a request should be handled. This protocol fully supports bidirectional streaming HTTP request handling, including optional request and response trailers.

The protocol definition currently looks like this:

```swift
public protocol HTTPServerRequestHandler<RequestReader, ResponseWriter>: Sendable {
    associatedtype RequestReader: ConcludingAsyncReader
    associatedtype ResponseWriter: ConcludingAsyncWriter

    func handle(
        request: HTTPRequest,
        requestContext: HTTPRequestContext,
        requestBodyAndTrailers: consuming sending RequestReader,
        responseSender: consuming sending HTTPResponseSender<ResponseWriter>
    ) async throws
}

```

The protocol uses two associated types that define how request bodies are read and response bodies are written. This gives HTTP Server implementations (and their users) the flexibility to provide custom readers and writers that fit their use cases, while keeping handler implementations agnostic to be used.

(Note: _Having these associated types basically requires all `HTTPServerRequestHandler` implementations to be generic_. Otherwise, if handler implementations would decide which concrete reader and writer types to use, that would constrain which servers they can be used with. Alternatives, such as moving the generics to the `handle` method, are currently being considered and you’re welcome to participate in the discussions.)

The reader and writer conform the `ConcludingAsyncReader` and `ConcludingAsyncWriter` types respectively, which enable streaming with a final element. In this case, the stream element type is `UInt8`, and the final element is and optional `HTTPFields` (from swift-http-types) representing trailers. These types are defined in the `AsyncStreaming` module defined in the `swift-http-api-proposal` repository, and they’re described in a bit more detail in the `HTTPRequestConcludingAsyncReader` and `HTTPResponseConcludingAsyncWriter` sections below.

When implementing `handle(request:requestContext:requestBodyAndTrailers:responseSender:)`, your handler receives four parameters:

1. **request** - The HTTP request headers and metadata
2. **requestContext** - Additional context about the request
3. **requestBodyAndTrailers** - A reader for streaming the request body and receiving trailers
4. **responseSender** - A mechanism for sending back responses

Here's how these pieces work together in a streaming echo handler that reads request data and writes it back.  
Let’s define a new `EchoHandler` that will echo back requests.

```swift
struct EchoHandler<
    ConcludingRequestReader: ConcludingAsyncReader<RequestReader, HTTPFields?> & ~Copyable & SendableMetatype,
    RequestReader: AsyncReader<UInt8, any Error> & ~Copyable,
    ConcludingResponseWriter: ConcludingAsyncWriter<ResponseWriter, HTTPFields?> & ~Copyable & SendableMetatype,
    ResponseWriter: AsyncWriter<UInt8, any Error> & ~Copyable
>: HTTPServerRequestHandler {
  func handle(
    request: HTTPRequest,
    requestContext: HTTPRequestContext,
    requestBodyAndTrailers: consuming sending ConcludingRequestReader,
    responseSender: consuming sending HTTPResponseSender<ConcludingResponseWriter>
  ) async throws {
    // We'll do this in a bit...
  }
}

```

The echo handler begins by wrapping the request async reader in an optional so we can consume it within the response writing closure. This is currently necessary because Swift currently lacks call-once closures:

```swift
var requestBodyAndTrailers = Optional(requestBodyAndTrailers)

```

We next send back a response with a 202 Accepted status. This consumes the response sender and returns a writer for the response body.

```swift
let responseBodyAndTrailers = try await responseSender.send(.init(status: .accepted))

```

Next, we use the response writer to echo back the request data, reading from the request reader and writing each chunk to the response.

```swift
try await responseBodyAndTrailers.produceAndConclude { writer in
  var writer = writer
  return try await requestBodyAndTrailers.take()!.consumeAndConclude { reader in
    try await reader.forEach { span in
      try await writer.write(span)
    }
  }
}

```

All in all, this is what the handler looks like:

```swift
func handle(
  request: HTTPRequest,
  requestContext: HTTPRequestContext,
  requestBodyAndTrailers: consuming sending ConcludingRequestReader,
  responseSender: consuming sending HTTPResponseSender<ConcludingResponseWriter>
) async throws {
  var requestBodyAndTrailers = Optional(requestBodyAndTrailers)
  let responseBodyAndTrailers = try await responseSender.send(.init(status: .accepted))
  try await responseBodyAndTrailers.produceAndConclude { writer in
    var writer = writer
    return try await requestBodyAndTrailers.take()!.consumeAndConclude { reader in
      try await reader.forEach { span in
        try await writer.write(span)
      }
    }
  }
}

```

This pattern ensures proper resource management through Swift's ownership system - the `consuming` and `sending` keywords guarantee that resources are used exactly once and transferred safely across concurrency boundaries.  
We also ensure at compile time that we only send a single response status back, followed by an optional body and trailers.

#### HTTPServerClosureRequestHandler

For simpler use cases, you don't always want to define a full conforming type. The `HTTPServerClosureRequestHandler` provides a convenient way to create request handlers using inline closures instead of defining a custom type that conforms to `HTTPServerRequestHandler`.

Its structure is straightforward: it just takes a closure with `HTTPServerRequestHandler/handle`’s same signature.  
An extension on `HTTPServer` provides an overload of `serve` that takes an `HTTPServerClosureRequestHandler`.

As a simple example, a server providing a Hello World service can be written in just a few lines of code:

```swift
let server = ... // create a concrete HTTPServer instance

try await server.serve { request, context, bodyReader, responseSender in
  let writer = try await responseSender.send(HTTPResponse(status: .ok))
  try await writer.writeAndConclude("Hello World".utf8.span, finalElement: nil)
}

```

This approach is perfect for simple servers, prototyping, or cases where you don't need the structure of a full conforming type.

#### HTTPResponseSender

The `HTTPResponseSender` is a critical piece of the API design that enforces proper HTTP response structure through Swift's type system. It's a non-copyable type that ensures responses are sent correctly and prevents common mistakes.

```swift
public struct HTTPResponseSender<ResponseWriter: ConcludingAsyncWriter & ~Copyable>: ~Copyable {
  public init(
      send: @escaping (HTTPResponse) async throws -> ResponseWriter,
      sendInformational: @escaping (HTTPResponse) async throws -> Void
  )

  consuming public func send(_ response: HTTPResponse) async throws -> ResponseWriter

  public func sendInformational(_ response: HTTPResponse) async throws
}

@available(*, unavailable)
extension HTTPResponseSender: Sendable {}

```

This type enforces the HTTP protocol's response flow through its API design:

**Informational responses (1xx status codes)** can be sent zero or more times using `sendInformational(_:)`. This method is not `consuming`, so you can call it multiple times. For example, you might send a `100 Continue` response before processing a large upload:

```swift
try await responseSender.sendInformational(HTTPResponse(status: .continue))

```

**Final responses** must be sent exactly once by calling `send(_:)`. \*\* This method is `consuming`, which means it takes ownership of the response sender and you cannot use it again. When you call `send(_``:)`, you get back a `ResponseWriter`:

```swift
let writer = try await responseSender.send(HTTPResponse(status: .ok)) 

```

After calling `send(_:)`, the `responseSender` is consumed and cannot be referenced again. This is enforced by the compiler, so you cannot send multiple final responses or send them in the wrong order.  
Once you have the `ResponseWriter`, you can write back the response body and optionally include trailers.

This design prevents common HTTP server bugs:

- **No duplicate responses** : The `consuming` keyword makes it impossible to send two final responses
- **Correct ordering** : You can't send a final response before informational ones are complete
- **Resource safety** : The type system ensures you properly complete the response lifecycle
- **Clear structure** : The API guides you toward the correct HTTP response pattern

For example, this code won't compile because it tries to use the response sender twice:

```swift
// This won't compile!
let writer1 = try await responseSender.send(HTTPResponse(status: .ok))
let writer2 = try await responseSender.send(HTTPResponse(status: .notFound)) // Error: responseSender was consumed

```

This compile-time safety is a key advantage of using non-copyable types - the API makes it impossible to misuse, rather than relying on runtime checks or documentation.

### Concrete NIO implementation

#### NIOHTTPServer

This is the concrete NIO-backed implementation for the `HTTPServer` protocol. It uses its own reader and writer types (`HTTPRequestConcludingAsyncReader` and `HTTPResponseConcludingAsyncWriter` respectively), described below.

```swift
public struct NIOHTTPServer: HTTPServer {
  public typealias RequestReader = HTTPRequestConcludingAsyncReader
  public typealias ResponseWriter = HTTPResponseConcludingAsyncWriter
  // ...
}

```

As a simple example, if a user wants to create an instance of a `NIOHTTPServer` that runs on localhost port 12345 and uses TLS, they can do so as follows:

```swift
let server = NIOHTTPServer(
    logger: logger,
    configuration: NIOHTTPServerConfiguration(
        bindTarget: .hostAndPort(host: "127.0.0.1", port: 12345),
        transportSecurity: .tls(
            certificateChain: /* some cert chain */,
            privateKey: /* some private key */
        )
    )
)

try await server.serve(handler: EchoHandler())

```

#### HTTPRequestConcludingAsyncReader

The `HTTPRequestConcludingAsyncReader` is a specialized reader for HTTP request bodies that enables incremental reading of body chunks followed by optional HTTP trailer fields. This type implements the `ConcludingAsyncReader` protocol (defined in the `swift-http-api-proposal` repository).

```swift
public struct HTTPRequestConcludingAsyncReader: ConcludingAsyncReader, ~Copyable {
  // ...
}

@available(*, unavailable)
extension HTTPRequestConcludingAsyncReader: Sendable {}

```

This reader allows you to consume the request body asynchronously, chunk by chunk, and then conclude with optional trailers arriving at the end of the request. Being non-copyable means this type uses Swift's ownership system to ensure that each request body is consumed exactly once, also preventing accidental double-reads or resource leaks.

For more details on the `ConcludingAsyncReader` pattern and how to use it, see the `AsyncStreaming` types defined in the `swift-http-api-proposal` repository.

#### HTTPResponseConcludingAsyncWriter

Mirroring the request reader, the `HTTPResponseConcludingAsyncWriter` is a specialised writer for HTTP response bodies that enables incremental writing of response bodies followed by optional HTTP trailer fields. This type implements the `ConcludingAsyncWriter` protocol (also defined in the `swift-http-api-proposal` repository).

```swift
public struct HTTPResponseConcludingAsyncWriter: ConcludingAsyncWriter, ~Copyable {
    // ...
}

@available(*, unavailable)
extension HTTPResponseConcludingAsyncWriter: Sendable {}

```

Like the request reader, this type is non-copyable to enforce single-use semantics through Swift's ownership system. Once you've written and concluded a response, the type system prevents you from accidentally writing to it again.

For more details on the `ConcludingAsyncWriter` pattern and how to use it, see the `AsyncStreaming` types defined in the `swift-http-api-proposal` repository.

* * *

## How You Can Help

As said above, this API is still in its infancy and we want everyone to provide feedback to improve it as much as we can.

You can find the existing HTTP Server abstract APIs (and the used `AsyncStreaming` readers and writers) in [GitHub - apple/swift-http-api-proposal: This repository contains a proposal for standardized HTTP client and server APIs for the Swift ecosystem · GitHub](https://github.com/apple/swift-http-api-proposal), and the NIO implementation at [GitHub - swift-server/swift-http-server · GitHub](https://github.com/swift-server/swift-http-server).

Please leave feedback either as responses to this post, or as issues in the repositories. Please tag any related forum posts with #http.

_Note: you will need the latest 6.3 development snapshot to use the current early builds. You can download it from [Install Swift | Swift.org](https://www.swift.org/install/) or install it via `swiftly` with `swiftly install 6.3-snapshot`._

## Links

📦 **Repositories**

- [GitHub - apple/swift-http-api-proposal: This repository contains a proposal for standardized HTTP client and server APIs for the Swift ecosystem · GitHub](https://github.com/apple/swift-http-api-proposal)
- [GitHub - swift-server/swift-http-server · GitHub](https://github.com/swift-server/swift-http-server)

**🔮 Networking Vision**

- [[Prospective Vision] Networking](https://forums.swift.org/t/prospective-vision-networking/85235)

**📱 HTTPClient API**

- [Designing an HTTP Client API for Swift](https://forums.swift.org/t/designing-an-http-client-api-for-swift/85254)

---

<div class="post-metadata">

**Author:** ![adam-fowler](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/adam-fowler/32/9266_2.png) [@adam-fowler](https://forums.swift.org/u/adam-fowler)\
**Post date:** [March 11, 2026, 10:37am UTC](https://forums.swift.org/t/designing-an-http-server-api-for-swift/85255/2 "2026-03-11T10:37:34Z")

</div>

This is great stuff. Defining a clear API layer between server implementation and framework has been something we are already doing with Hummingbird. But to be able to do this across the whole eco-system opens a whole load of additional possibilities.

Have you considered making the `HTTPRequestContext` generic as well. I currently don’t see anyway to pass server implementation details to the framework layer. For instance a framework might want the remote IP address to perform rate limiting. With the current protocol design I don’t see how this could be achieved. You could just add these values to `HTTPRequestContext` but there might be other values, as yet undefined, that server implementations want to pass. I guess you could do this with Task locals but isn’t it preferable we test for the existence of any additional context information at compile time over run time.

I’m not a great fan of some of the symbols and find them quite a mouthful eg`HTTPRequestConcludingAsyncReader`. But I don’t have any sensible alternatives.

The NIO server implementation is dependent on both NIOSSL, NIOHTTP2 and related libraries. Hummingbird has always tried to only include the dependencies required eg a vanilla HTTP/1.1 server wouldn’t required compiling and linking TLS, HTTP2 code. If we were to move to the NIO default implementation we would lose that. Would using traits to enable/disable elements of the server implementation be something you would consider looking into?

In whole though this is great move forward.

---

<div class="post-metadata">

**Author:** ![guscairo](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/guscairo/32/39367_2.png) [@guscairo](https://forums.swift.org/u/guscairo)\
**Post date:** [March 11, 2026, 4:20pm UTC](https://forums.swift.org/t/designing-an-http-server-api-for-swift/85255/3 "2026-03-11T16:20:31Z")

</div>

> [@adam-fowler](#):
>
> This is great stuff. Defining a clear API layer between server implementation and framework has been something we are already doing with Hummingbird. But to be able to do this across the whole eco-system opens a whole load of additional possibilities.

Thank you!

> [@adam-fowler](#):
>
> Have you considered making the `HTTPRequestContext` generic as well. I currently don’t see anyway to pass server implementation details to the framework layer. For instance a framework might want the remote IP address to perform rate limiting. With the current protocol design I don’t see how this could be achieved. You could just add these values to `HTTPRequestContext` but there might be other values, as yet undefined, that server implementations want to pass. I guess you could do this with Task locals but isn’t it preferable we test for the existence of any additional context information at compile time over run time.

Yes, this may have warranted an aside in the post, actually: `HTTPRequestContext` is really sort of a placeholder at this point. We briefly discussed with some folks what this should be, and Generics and Task Locals were both considered, but ultimately we decided it was probably better to open this particular topic for discussion with the community, since (as you rightly pointed out) there are several ways of going about it.

I suggest we discuss this over on GitHub, since we've got this issue: [Implementation-specific request contexts · Issue #28 · swift-server/swift-http-server · GitHub](https://github.com/swift-server/swift-http-server/issues/28)

> [@adam-fowler](#):
>
> I’m not a great fan of some of the symbols and find them quite a mouthful eg`HTTPRequestConcludingAsyncReader`. But I don’t have any sensible alternatives.

I do agree names are a mouthful 🙂 and I'll be happy to do some bikeshedding.

> [@adam-fowler](#):
>
> The NIO server implementation is dependent on both NIOSSL, NIOHTTP2 and related libraries. Hummingbird has always tried to only include the dependencies required eg a vanilla HTTP/1.1 server wouldn’t required compiling and linking TLS, HTTP2 code. If we were to move to the NIO default implementation we would lose that. Would using traits to enable/disable elements of the server implementation be something you would consider looking into?

I think this is a good suggestion and something we should consider. I've created [Consider using traits (or some other mechanism) to remove overhead of unused features · Issue #66 · swift-server/swift-http-server · GitHub](https://github.com/swift-server/swift-http-server/issues/66)

---

<div class="post-metadata">

**Author:** ![ST1](https://avatars.discourse-cdn.com/v4/letter/s/e9a140/32.png) [@ST1](https://forums.swift.org/u/ST1)\
**Post date:** [March 12, 2026, 2:53pm UTC](https://forums.swift.org/t/designing-an-http-server-api-for-swift/85255/4 "2026-03-12T14:53:58Z")

</div>

First of all, thank you very much for all the work you’ve put into this!

I’ve been going through the API, and I might have missed something, so I’d like to ask for a bit of clarification. I was wondering about the possibility of sending a response body without unnecessary copies, perhaps by using some kind of intermediate type or zero-copy approach?

To illustrate with a concrete example: when sending a JSON response, the typical flow seems to be: we encode our model into Data, and then we copy that data into NIO ByteBuffer. For large responses, these extra copies can significantly impact performance, and I'd really like to find a way to avoid them.

Perhaps we could design some kind of intermediate type that can be consumed later without copying by "taking" its contents rather than copying them.

Something like that:

```swift
public struct RawBytes: ~Copyable {
   let pointer: UnsafeMutableRawPointer?
   var count: Int
}

struct CustomData: ~Copyable {
  ... 
  consuming func takeRawBytes() -> RawBytes {
    discard self
    return RawBytes(...)
  }
  ...
}

// in serve handler
try await writer.writeAndConclude(customData.takeRawBytes(), finalElement: nil)

// Init ByteBuffer from RawBytes
ByteBuffer(rawBytes: bytes)

```

---

<div class="post-metadata">

**Author:** ![0xTim](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/0xtim/32/27968_2.png) [@0xTim](https://forums.swift.org/u/0xTim)\
**Post date:** [March 12, 2026, 3:21pm UTC](https://forums.swift.org/t/designing-an-http-server-api-for-swift/85255/5 "2026-03-12T15:21:00Z")

</div>

The issue with this is `Data` as it currently exists isn’t a great type for this kind of thing and the HTTP Server, and by extension NIO’s ByteBuffer need to support streaming and other features that `Data` currently doesn’t. I imagine some part of the networking vision is to push for Swift to provide something like a writeable `Span` that would allow you to take the output from a JSON encoder, or other encoder and feed it directly into the response without any copies, much in the same way your example works, without the unsafe types

---

<div class="post-metadata">

**Author:** ![guscairo](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/guscairo/32/39367_2.png) [@guscairo](https://forums.swift.org/u/guscairo)\
**Post date:** [March 12, 2026, 4:40pm UTC](https://forums.swift.org/t/designing-an-http-server-api-for-swift/85255/6 "2026-03-12T16:40:12Z")

</div>

Thanks for going over the proposal. Pretty much what @0xTim has said: sadly we're currently limited by the types we've got available. We're aware of the copies here, but the plan is to get some new types in place that will make all of this more efficient.

---

<div class="post-metadata">

**Author:** ![Les\_Pruszynski](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/les_pruszynski/32/797_2.png) [@Les\_Pruszynski](https://forums.swift.org/u/Les_Pruszynski)\
**Post date:** [March 12, 2026, 5:17pm UTC](https://forums.swift.org/t/designing-an-http-server-api-for-swift/85255/7 "2026-03-12T17:17:39Z")

</div>

Clearly I have misunderstood the “Networking Vision” document. My feeling after reading it was that the NIO thing is old and that we should be looking for something better, particularly because the Swift language has moved on considerably. Here though, you are basing the whole stack on NIO in spite of what the networking vision document says?

---

<div class="post-metadata">

**Author:** ![ST1](https://avatars.discourse-cdn.com/v4/letter/s/e9a140/32.png) [@ST1](https://forums.swift.org/u/ST1)\
**Post date:** [March 12, 2026, 6:07pm UTC](https://forums.swift.org/t/designing-an-http-server-api-for-swift/85255/8 "2026-03-12T18:07:03Z")

</div>

Yes, I'm quite familiar with the current limitations of Data. I simply wanted to raise this point because it's quite important for server-side Swift.

---

<div class="post-metadata">

**Author:** ![lukasa](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lukasa/32/1232_2.png) [@lukasa](https://forums.swift.org/u/lukasa)\
**Post date:** [March 12, 2026, 6:47pm UTC](https://forums.swift.org/t/designing-an-http-server-api-for-swift/85255/9 "2026-03-12T18:47:20Z")

</div>

> [@Les\_Pruszynski](#):
>
> Here though, you are basing the whole stack on NIO in spite of what the networking vision document says?

Quite the opposite. Quoting the original post:

> [@guscairo](#):
>
> We’ve got two main, high-level goals as part of this effort:
> 
> - Provide an abstract API interface, to be used by users who may want to build on top of the HTTP Server in an implementation-agnostic way (primarily library developers).
> - Provide a high-performance concrete implementation of this interface based on SwiftNIO that can be used out-of-the-box.

We intend to build a SwiftNIO-based version of this API because SwiftNIO exists, today, and is capable of handling these use-cases, today. That allows the community to get experience with these APIs and validate that they do the necessary work.

When alternatives to or replacements for NIO arrive, they will be able to slot underneath this API. This will enable applications to be moved onto something newer without needing to completely rebuild.

But note that the Networking vision document quite explicitly disclaims your reading of it:

> **Is the long-term vision to phase out SwiftNIO?**
> 
> No. We're unifying the underlying primitives across SwiftNIO, Network.framework, URLSession, and others to reduce duplication and increase cross-platform consistency.

NIO will remain supported for the foreseeable future.

---

<div class="post-metadata">

**Author:** ![kiel](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/kiel/32/1392_2.png) [@kiel](https://forums.swift.org/u/kiel)\
**Post date:** [March 13, 2026, 7:16am UTC](https://forums.swift.org/t/designing-an-http-server-api-for-swift/85255/10 "2026-03-13T07:16:29Z")

</div>

Is the intention that the HTTP client aspect of this vision would be used by apps that would ordinarily use URLSession for HTTP requests?

---

<div class="post-metadata">

**Author:** ![Avi](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/avi/32/2962_2.png) [@Avi](https://forums.swift.org/u/Avi)\
**Post date:** [March 13, 2026, 8:08am UTC](https://forums.swift.org/t/designing-an-http-server-api-for-swift/85255/11 "2026-03-13T08:08:22Z")

</div>

It reads that way to me. The vision doc speaks of URLSession being one of several implementations.

---

<div class="post-metadata">

**Author:** ![guscairo](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/guscairo/32/39367_2.png) [@guscairo](https://forums.swift.org/u/guscairo)\
**Post date:** [March 18, 2026, 5:56pm UTC](https://forums.swift.org/t/designing-an-http-server-api-for-swift/85255/13 "2026-03-18T17:56:34Z")

</div>

Hey Kiel, would you mind posting questions related to the Client API in the [other post](https://forums.swift.org/t/designing-an-http-client-api-for-swift/85254)?

---

<div class="post-metadata">

**Author:** ![pbwo](https://avatars.discourse-cdn.com/v4/letter/p/439d5e/32.png) [@pbwo](https://forums.swift.org/u/pbwo)\
**Post date:** [June 26, 2026, 10:31am UTC](https://forums.swift.org/t/designing-an-http-server-api-for-swift/85255/14 "2026-06-26T10:31:47Z")

</div>

per proposal there is the intent to provide for a http server api.  
yet network apis can be distinguished at a lower level aswell, having a distinction between a stream based and a state based network api, the http server api stand build upon.

essentially the postgresnio/valkey connection pool module with a subscription model for a generic server/client instance for connection pooling/registry would simplify the instantiation of clients and servers tremendously.

most favorable would be the community driven approach to common pitfalls, aswell as the discussion/inclusion/exclusion of certain exceptions/norms etc. that could improve clients/servers independent from the customization at the api surface they expose.

here is the "most recent" discussion, i could find.

the http server is a nodge in the right direction but is goes already too far excluding the possibilities inbetween?
