apple/swift-nio
Event-driven network application framework for high performance protocol servers & clients, non-blocking.
Healthy across the board
Permissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 3d ago
- ✓28+ active contributors
- ✓Distributed ownership (top contributor 23% of recent commits)
Show 3 more →Show less
- ✓Apache-2.0 licensed
- ✓CI configured
- ✓Tests present
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/apple/swift-nio)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/apple/swift-nio on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: apple/swift-nio
Generated by RepoPilot · 2026-05-10 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/apple/swift-nio shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across the board
- Last commit 3d ago
- 28+ active contributors
- Distributed ownership (top contributor 23% of recent commits)
- Apache-2.0 licensed
- CI configured
- Tests present
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live apple/swift-nio
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/apple/swift-nio.
What it runs against: a local clone of apple/swift-nio — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in apple/swift-nio | Confirms the artifact applies here, not a fork |
| 2 | License is still Apache-2.0 | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 33 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of apple/swift-nio. If you don't
# have one yet, run these first:
#
# git clone https://github.com/apple/swift-nio.git
# cd swift-nio
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of apple/swift-nio and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "apple/swift-nio(\\.git)?\\b" \\
&& ok "origin remote is apple/swift-nio" \\
|| miss "origin remote is not apple/swift-nio (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
&& ok "license is Apache-2.0" \\
|| miss "license drift — was Apache-2.0 at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f "Sources/NIOCore/EventLoop.swift" \\
&& ok "Sources/NIOCore/EventLoop.swift" \\
|| miss "missing critical file: Sources/NIOCore/EventLoop.swift"
test -f "Sources/NIOCore/Channel.swift" \\
&& ok "Sources/NIOCore/Channel.swift" \\
|| miss "missing critical file: Sources/NIOCore/Channel.swift"
test -f "Sources/NIOCore/ChannelPipeline.swift" \\
&& ok "Sources/NIOCore/ChannelPipeline.swift" \\
|| miss "missing critical file: Sources/NIOCore/ChannelPipeline.swift"
test -f "Sources/NIOCore/ByteBuffer.swift" \\
&& ok "Sources/NIOCore/ByteBuffer.swift" \\
|| miss "missing critical file: Sources/NIOCore/ByteBuffer.swift"
test -f "Sources/NIOPosix/PosixEventLoop.swift" \\
&& ok "Sources/NIOPosix/PosixEventLoop.swift" \\
|| miss "missing critical file: Sources/NIOPosix/PosixEventLoop.swift"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 33 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~3d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/apple/swift-nio"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
SwiftNIO is a non-blocking, event-driven network application framework for Swift that provides the core abstractions (EventLoop, Channel, ChannelPipeline) needed to build high-performance protocol servers and clients. It's Apple's answer to Netty, offering NIOCore (abstractions), NIOPosix (POSIX-based I/O with epoll/kqueue), and NIOEmbedded (testing) modules that work across Linux, macOS, and other platforms. Single-package monorepo structure: Sources/ contains NIOCore/, NIOPosix/, NIOEmbedded/, NIOConcurrencyHelpers/, NIOFoundationCompat/, and NIOTLS/ as separate targets; Tests/ mirrors this structure; Benchmarks/ has NIOCoreBenchmarks and NIOPosixBenchmarks with perf thresholds tracked by Swift version (6.1, 6.2, 6.3, nightly-main); .github/workflows/ drives the CI matrix; all governed by Package.swift.
👥Who it's for
Swift backend engineers, library maintainers, and protocol developers who need to build network services (HTTP servers, databases, load balancers, proxies) with minimal latency and maximum throughput. Also used by downstream frameworks like swift-nio-ssl, swift-nio-http2, and swift-nio-transport-services.
🌱Maturity & risk
Highly mature and production-ready. SwiftNIO is SSWG-graduated (see badge in README), has extensive CI coverage across 15+ workflows (macos_tests.yml, unit_tests.yml, benchmarks.yml, etc.), comprehensive benchmark tracking with Thresholds/, and is actively maintained with regular releases. The codebase is ~7.8M lines of Swift with established patterns and deprecation management.
Very low risk for production use. Apple maintains it directly, but adopters should note: this is a low-level abstraction (similar to Netty) requiring careful thread-safety reasoning; the ecosystem is split across 6 related repos (swift-nio-ssl, swift-nio-http2, swift-nio-extras, swift-nio-transport-services, swift-nio-ssh), so upgrades may ripple; and Concurrency model integration is ongoing (see workflows for swift_6_language_mode.yml). Check release notes for breaking changes between major versions.
Active areas of work
Active development on Swift 6 language mode compatibility (swift_6_language_mode.yml workflow), concurrent async/await integration (NIOAsyncChannel benchmarks, TCPEchoAsyncChannel.swift), and platform expansion (wasm_swift_sdk.yml, android_swift_sdk.yml, static_sdk.yml, cxx_interop.yml). Benchmarking is rigorous with p90 thresholds per release tracked in Benchmarks/Thresholds/.
🚀Get running
git clone https://github.com/apple/swift-nio.git
cd swift-nio
# Build and test using Swift Package Manager
swift build
swift test
# Run benchmarks
cd Benchmarks
swift run NIOCoreBenchmarks
Daily commands:
No 'dev server' per se (NIO is a framework, not an application). To run examples/tests: swift test executes all unit tests across targets. To run benchmarks: swift run -c release NIOPosixBenchmarks or swift run -c release NIOCoreBenchmarks. CI runs via GitHub Actions: see .github/workflows/main.yml for the full matrix.
🗺️Map of the codebase
Sources/NIOCore/EventLoop.swift— Core abstraction for the event loop—every async operation in NIO depends on understanding how EventLoop schedules and executes tasks.Sources/NIOCore/Channel.swift— Primary interface for I/O operations; all protocol handlers interact with channels to read/write data.Sources/NIOCore/ChannelPipeline.swift— Defines the handler pipeline architecture—critical for understanding how data flows through and is transformed by handlers.Sources/NIOCore/ByteBuffer.swift— NIO's buffer abstraction for memory-efficient data handling; heavily used throughout the codebase.Sources/NIOPosix/PosixEventLoop.swift— Platform-specific event loop implementation using epoll/kqueue; essential for understanding actual I/O multiplexing.Sources/NIOCore/ChannelHandler.swift— Base protocol for all channel handlers; defines the handler lifecycle and inbound/outbound event model.Package.swift— SPM manifest defining the module structure, dependencies, and platforms—required reading to understand how NIO is organized.
🧩Components & responsibilities
- EventLoop (Swift async/await, EventLoopFuture, epoll/kqueue) — Executes scheduled tasks and callbacks in FIFO order; integrates with platform I/O multiplexer (epoll/kqueue) to wake on socket events
- Failure mode: If event loop is blocked by slow task, all channels on that loop experience latency
- Channel — Represents a single TCP/UDP connection; routes read/write
🛠️How to make changes
Add a Custom ChannelHandler
- Create a new struct/class conforming to ChannelInboundHandler and/or ChannelOutboundHandler in Sources/NIOCore/ (
Sources/NIOCore/ChannelHandler.swift) - Implement required channelRead(), channelActive(), or errorCaught() methods depending on handler type (
Sources/NIOCore/ChannelHandler.swift) - Add handler to pipeline in server bootstrap or channel configuration using pipeline.addHandler() (
Sources/NIOCore/ChannelPipeline.swift) - Write unit tests in Tests/ directory following existing test patterns (
Tests)
Create a New Protocol Server
- Create server bootstrap using ServerBootstrap() from NIOPosix or appropriate platform module (
Sources/NIOPosix/PosixEventLoopGroup.swift) - Implement custom ChannelInitializer closure to configure the handler pipeline for your protocol (
Sources/NIOCore/ChannelPipeline.swift) - Bind to port and handle incoming connections using bootstrap.bind(host:port:) returning an EventLoopFuture (
Sources/NIOCore/EventLoopPromise.swift) - Add protocol-specific handlers (frame decoder, encoder, business logic) to the channel pipeline (
Sources/NIOCore/ChannelHandler.swift)
Implement Async/Await Channel Operations
- Use NIOAsyncChannel wrapper to convert callback-based channel to AsyncSequence (
Sources/NIOCore/AsyncChannelIO.swift) - Leverage async for loops with inbound AsyncSequence and writeOutbound() async methods (
Sources/NIOCore/NIOAsyncSequence.swift) - Wrap EventLoopFuture operations with EventLoopFuture.get() to convert to async/await (
Sources/NIOCore/EventLoopPromise.swift)
🔧Why these technologies
- Swift async/await and structured concurrency — Modern Swift concurrency model provides type-safe async operations and integrates seamlessly with NIO's event loop for ergonomic I/O
- Callback-based EventLoopFuture/Promise model — Pre-dating Swift async/await, provides composable async primitives with backpressure and ordering guarantees for fine-grained control
- epoll (Linux) / kqueue (BSD/macOS) — Most efficient multiplexed I/O on respective platforms, allowing high concurrency with minimal thread overhead
- Copy-on-Write ByteBuffer — Reduces allocations and memory copies when passing buffers through the handler pipeline
⚖️Trade-offs already made
-
Event-driven, non-blocking I/O vs threaded per-connection model
- Why: Allows handling thousands of concurrent connections efficiently without thread overhead
- Consequence: Developers must avoid blocking operations (file I/O, computation) on the event loop; long-running tasks must be dispatched to thread pools
-
Handler pipeline processes events sequentially within a channel
- Why: Ensures ordering and prevents race conditions on per-channel state
- Consequence: Slow handlers block the event loop for that channel; handlers must be fast or offload work
-
Supporting both callback-based (Future/Promise) and async/await APIs
- Why: Gradual adoption of Swift async; allows new code to use async/await while existing callback code remains compatible
- Consequence: Increased API surface; some redundancy between the two models
-
Single-threaded event loop per core by default
- Why: Maximizes cache locality and eliminates synchronization overhead
- Consequence: CPU-bound work on the event loop is not parallelized; must use thread pools or multi-loop distribution
🚫Non-goals (don't propose these)
- Does not provide application-level protocol implementations (e.g., HTTP, WebSocket, TLS); those are in separate repositories (swift-nio-http2, swift-nio-ssl)
- Does not include built-in load balancing or clustering; focus is on single-process network I/O
- Does not abstract away platform differences completely; platform-specific optimizations are exposed (e.g., epoll vs kqueue options)
🪤Traps & gotchas
- EventLoop thread-safety: All ChannelHandler code must run on the EventLoop thread; accessing shared state from other threads requires
eventLoop.execute()or synchronization primitives in NIOConcurrencyHelpers. 2. ByteBuffer lifecycle: ByteBuffer is reference-counted; mutations can be unsafe if shared across threads without proper locking. 3. No built-in TLS: TLS support is in a separate repo (swift-nio-ssl); importing it requires an external dependency. 4. Selector platform differences: epoll (Linux) and kqueue (macOS/BSD) have subtle behavioral differences in error handling and edge cases; tests in Tests/NIOPosixTests/ChannelTests/ cover these. 5. Swift Concurrency interop is ongoing: async/await integration (NIOAsyncChannel) is recent; older Future-based code still exists and mixes paradigms. 6. C interop complexity: NIOPosix uses C for socket ops (Sources/NIOPosix/SocketAddress.c); changes here require C compilation and testing on multiple OSes.
🏗️Architecture
💡Concepts to learn
- Event-driven, non-blocking I/O multiplexing — NIO's entire design hinges on using epoll/kqueue to handle thousands of connections per thread without blocking; understanding how selectors avoid the C10K problem is essential to using NIO correctly.
- Channel and ChannelPipeline (protocol composition) — The Channel abstraction and handler pipeline are the core API model in NIO; learning how to compose ChannelHandlers into a pipeline is the primary skill for building protocol implementations.
- EventLoop and thread-per-core scheduling — NIO binds one EventLoop per CPU thread to minimize context switching and cache misses; understanding the EventLoop scheduling model is critical to avoiding hidden contention and deadlocks.
- Zero-copy ByteBuffer with reference counting — NIO's ByteBuffer is designed to avoid allocations and copies in the hot path; understanding reference semantics and slice safety is essential to writing efficient handlers.
- Backpressure and Channel writeability — NIO uses a write buffer high-water mark mechanism to signal backpressure to handlers; misunderstanding writeability can lead to unbounded memory growth under load.
- Future and Promise (legacy async model, now async/await) — Much NIO code still uses Futures and Promises; understanding how they compose and chain is necessary to read existing handler implementations and tests.
- ChannelHandler inbound/outbound event flow — Handlers must understand the direction and order of events (inbound: read, close; outbound: write, flush) to avoid protocol violations and deadlocks.
🔗Related repos
apple/swift-nio-ssl— Provides TLS/SSL support on top of NIOCore; required for building HTTPS servers and encrypted channels.apple/swift-nio-http2— HTTP/2 protocol implementation and framing on top of NIOCore; enables modern HTTP server and client development.apple/swift-nio-extras— Collection of useful ChannelHandlers and utilities (LengthFieldPrepender, LengthFieldBasedFrameDecoder, etc.) for common protocol patterns.apple/swift-nio-transport-services— First-class EventLoop and Channel implementations for macOS, iOS, tvOS, and watchOS using Network.framework; enables NIO on Apple platforms.vapor/vapor— Popular Swift web framework that builds on top of NIO for its HTTP and WebSocket handling.
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add integration tests for AsyncChannel with backpressure scenarios
The repo has benchmark thresholds for NIOAsyncChannel.init across multiple Swift versions (6.1, 6.2, 6.3, nightly-main, nightly-next) in Benchmarks/Thresholds/, but IntegrationTests lacks dedicated backpressure and flow-control tests for AsyncChannel. Given that NIO is used for high-performance servers, ensuring correct backpressure behavior under load is critical. This would involve creating new integration test cases similar to the allocation-counter-tests-framework structure.
- [ ] Create new directory: IntegrationTests/async-channel-backpressure-tests/
- [ ] Add Package.swift manifest for the integration test
- [ ] Write tests covering: rapid writes with slow reads, buffer overflow scenarios, and pause/resume cycles
- [ ] Reference Benchmarks/Benchmarks/NIOPosixBenchmarks/TCPEchoAsyncChannel.swift as a baseline for AsyncChannel usage patterns
- [ ] Add test execution to existing CI workflows (e.g., .github/workflows/unit_tests.yml)
Add Windows support workflow in GitHub Actions
The repo has comprehensive CI workflows (.github/workflows/) for macOS, Android, WASM, and Swift 6 language mode, but notably lacks a Windows CI workflow. Swift 6.0+ has improved Windows support, and NIO as a core networking framework should validate cross-platform compatibility. This would help catch Windows-specific regressions early.
- [ ] Create .github/workflows/windows_tests.yml following the pattern of macos_tests.yml and swift_test_matrix.yml
- [ ] Configure matrix strategy for Windows-latest runner with Swift toolchain installation
- [ ] Ensure tests cover both Posix and core modules (reference .github/workflows/unit_tests.yml for test targets)
- [ ] Add conditional step to handle Windows-specific socket/networking APIs if needed
- [ ] Document in CONTRIBUTING.md that Windows testing is now available
Create detailed API migration guide for NIO 2.x releases with docstring examples
The repo has a CONTRIBUTING.md but lacks a specific migration/changelog guide with code examples for breaking changes between NIO 2.x versions. With benchmarks tracking performance across versions (Benchmarks/Thresholds/) and multiple dependent packages (swift-nio-ssl, swift-nio-http2, swift-nio-extras), contributors and users need clear guidance on API changes. This should be a versioned markdown file with before/after code samples.
- [ ] Create MIGRATION_GUIDE.md in the repo root documenting NIO 2.0→2.1→2.2+ changes
- [ ] Reference the .github/release.yml configuration to understand what release notes are generated
- [ ] Include concrete examples: EventLoopGroup initialization changes, Channel handler refactoring, AsyncChannel adoption patterns
- [ ] Link to specific source files in Sources/ directory that demonstrate new APIs
- [ ] Add section on updating dependent packages (swift-nio-ssl, swift-nio-http2, etc.) to compatible versions
🌿Good first issues
- Add documentation and examples for
ChannelHandlerlifecycle methods (channelActive, channelInactive, exceptionCaught) in Sources/NIOCore/ChannelHandler.swift—many new users misunderstand when these fire. Create a markdown guide or expand the docstrings with code examples. - Extend Benchmarks/Benchmarks/NIOPosixBenchmarks/TCPEchoAsyncChannel.swift to include a WebSocket echo server variant using the same async/await pattern, and add a p90 threshold in Benchmarks/Thresholds/ to track performance across Swift versions.
- Add unit tests for error cases in Sources/NIOPosix/Selector.swift (EINTR, ENOMEM during select(), platform-specific edge cases) that are currently underrepresented; focus on Tests/NIOPosixTests/SelectorTests/ and verify behavior on both Linux and macOS.
⭐Top contributors
Click to expand
Top contributors
- @rnro — 23 commits
- @simonjbeaumont — 7 commits
- @Lukasa — 7 commits
- @scottmarchant — 7 commits
- @fabianfett — 6 commits
📝Recent commits
Click to expand
Recent commits
8bbd97b— Disable nightly until 6.4 builds are available (#3585) (kukushechkin)37e191d— Strip Transfer-Encoding when Content-Length is present in HTTPEncoder (#3583) (fabianfett)1c8b29c— make internal FTSInfo take CInt (#3586) (weissi)f71c8d2— Move historycal dependency back to NIOFoundationCompat (#3581) (Cyberbeni)3800079— Split FoundationEssentials extensions from NIOFoundationCompat (#3567) (Cyberbeni)32e3d86— Add multi-version matrix support to Wasm Swift SDK workflow (#3575) (inductor)a57cc53— TranslateHTTPHeaderValidationTeststo Swift testing (#3579) (fabianfett)d36223d— Add support for --security-opt docker flags in custom CI jobs (#3580) (simonjbeaumont)cd67104— Preserve getaddrinfo error code in SocketAddressError (#3558) (thisismanan)e0ee947— Bump swiftlang/github-workflows/.github/workflows/soundness.yml from 0.0.7 to 0.0.10 (#3572) (dependabot[bot])
🔒Security observations
SwiftNIO demonstrates a mature security posture as an SSWG graduated project. The codebase structure shows good organization with proper build configuration and CI/CD workflows. Primary concerns are: (1) the incomplete SECURITY.md documentation which should be completed to provide clear security vulnerability response procedures, (2) system-level testing frameworks in IntegrationTests that require careful handling and documentation, and (3) general best practices for sensitive configuration management in benchmark thresholds. No obvious hardcoded credentials, SQL injection risks, or XSS vulnerabilities are evident from the file structure. The project appears to follow security best practices with multiple Swift version support and backward compatibility considerations for security patches.
- Medium · Incomplete Security Policy Documentation —
SECURITY.md. The SECURITY.md file appears to be truncated or incomplete. The security vulnerability response process documentation cuts off mid-sentence when describing patch release procedures. This could lead to confusion about the security support timeline and version coverage. Fix: Complete the SECURITY.md file with full documentation of the security vulnerability disclosure process, supported versions, and contact procedures. Ensure clarity on which versions receive patches and the timeline for security updates. - Low · Potential Secret Exposure in Allocation Counter Framework —
IntegrationTests/allocation-counter-tests-framework/. The IntegrationTests directory contains C code files (atomic-counter.c, hooked-functions-*.c) that interact with system-level memory allocation. While this is likely legitimate for testing purposes, the framework could potentially expose sensitive information if misconfigured or if test data is committed. Fix: Ensure that no sensitive data or credentials are included in test data. Add clear documentation about what this allocation counter framework does and why system-level hooking is necessary. Consider adding integration test exclusions to .gitignore if appropriate. - Low · Benchmark Threshold Files May Contain Sensitive Configuration —
Benchmarks/Thresholds/. The Benchmarks/Thresholds directory contains JSON files with performance metrics. While not inherently sensitive, if these thresholds are used to make security or reliability decisions, the threshold files should be treated as critical configuration. Fix: Review the purpose and usage of benchmark threshold files. If they influence security or reliability decisions, implement access controls and change tracking. Document their significance in the repository security guidelines.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.