# Moya: a compile-time network abstraction layer for Swift apps

> Moya wraps Alamofire behind an enum of endpoints, so API calls are checked by the compiler and test stubs become part of the design. It suits Swift teams with a fixed set of endpoints, and it is a poor fit for one-off requests.

**Moya/Moya** — Network abstraction layer written in Swift.

- Repository: https://github.com/Moya/Moya
- Website: https://moya.github.io
- Stars: 15,353 · Forks: 1,994
- Language: Swift
- License: MIT
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/moya-moya

## The ad hoc APIManager problem Moya was written to replace

The README opens with a blunt observation: developers already use Alamofire to hide URLSession, then write their own network layer anyway, usually named APIManager or NetworkModel, and "they always end in tears." Moya's answer is to make that layer a library instead of a folder. You describe each endpoint once as a case in an enum, and the library handles URL construction, parameters, headers and the actual request.

The audience is narrow but well defined. It is a Swift team building an app against an API surface that is known at build time: a login endpoint, a feed, a profile update. If your app fires requests at URLs assembled at runtime from server-provided templates, an enum of cases is the wrong shape. Moya also assumes you are already on Alamofire, since Moya sits on top of it rather than replacing it.

The README names three costs of the ad hoc layer: it makes new apps hard to start, existing apps hard to maintain, and unit tests hard to write. Only the third is a claim Moya can actually enforce, through its TargetType protocol and its stub support.

## How TargetType turns endpoints into compiler-checked values

The mechanism is a protocol conformance. You write an enum whose cases are your endpoints, conform it to TargetType, and implement the required properties: baseURL, path, method, task, and headers. Each case supplies its own values, so the set of valid requests is the set of enum cases and nothing else.

That is where the compile-time checking the README advertises comes from. There is no string path to mistype at a call site, because call sites reference enum cases. Adding an endpoint means adding a case, and the compiler will tell you if the new case does not satisfy the protocol.

The README describes the project's goal as simple enough that common things are easy and comprehensive enough that complicated things are also easy. The trade-off is visible in the same design: a request shape that does not fit the properties TargetType exposes has to be expressed through the task and headers values, and the README does not enumerate edge cases there. The Vision.md file in the repository root is where the maintainers state project direction, which is worth reading before you commit to the abstraction.

## Installing Moya with Swift Package Manager and making a first request

Swift Package Manager is the path the README documents first. Add the package as a dependency using the version range from the README, then name Moya as a target dependency.

```swift
.package(url: "https://github.com/Moya/Moya.git", .upToNextMajor(from: "15.0.0"))
```

The README's full PackageDescription example also shows the reactive extensions as target dependencies, so if you want Combine support you list CombineMoya in the same dependencies array as Moya itself. Note the Combine caveat in the README: CombineMoya requires Xcode 11.5.0 or later, and on earlier versions you must add Combine as a weakly linked framework to your application target.

CocoaPods users instead add a subspec to the Podfile and run pod install. The README lists four forms, and the subspec you pick decides which module you import.

```rb
pod 'Moya', '~> 15.0'

# or

pod 'Moya/RxSwift', '~> 15.0'
```

Carthage users put github "Moya/Moya" ~> 15.0 in a Cartfile and run carthage update --use-xcframeworks. Accio users configure Package.swift the same way as SwiftPM and then run accio update instead of swift package update.

Once the dependency resolves, import the framework with import Moya and conform an enum to TargetType. The repository ships two runnable samples under Examples, named Basic and Multi-Target, and the README's instruction for them is to download the repo, run carthage update, open Moya.xcodeproj, pick a scheme and build. That is the fastest way to see a working TargetType before writing your own.

## Stub support and where the abstraction stops paying off

The feature the README leans on hardest is testing. It calls test stubs "first-class citizens" and says unit testing becomes super-easy. The reason is structural: because requests are enum cases, a test can substitute a stub response for a case without a live server. The Tests directory in the repository layout is where the project's own suite lives, and the Examples directory holds the two sample apps.

The limitation is the flip side of the same design. Moya is a layer over Alamofire, so anything Alamofire cannot express, Moya cannot either, and debugging a failed request means reasoning through two libraries rather than one. The README's compatibility table also pins Alamofire to 5.X for Moya 15 and later, so an Alamofire major version bump is a Moya upgrade question, not an independent one.

Version drift is the other real cost. The latest release listed for the repository is 15.0.3 from 2022-08-12, and the README's table maps Swift 5.2 and later to Moya 15.0.0 or above. The README states the project is under development and used in Artsy's auction app, and the repository's last push was on 2026-07-14, so the codebase does move even though the published release is older. What the README does not document is a rollback path if a Moya upgrade breaks a target; the migration guides under docs are the closest thing, and they cover major versions only.

## Moya against calling Alamofire directly

The honest alternative is Alamofire on its own, which is what Moya wraps. With Alamofire you call a request method with a URL and parameters at the call site. With Moya you declare a TargetType case once and call it from anywhere. The difference is where mistakes surface: at runtime in the first case, at compile time in the second, but only for the parts of the request the enum encodes.

Alamofire's approach is lighter. There is no protocol to conform to, no enum to extend, and no second library in the stack when you are debugging. For an app with three endpoints, or a script that fetches one JSON document, Moya's structure is overhead you will pay for and never collect on. For an app with thirty endpoints shared across several screens and a test suite, the enum is the thing that keeps the call sites from drifting apart.

The README frames this as a question rather than a verdict: if you use Alamofire to abstract away URLSession, why not use something to abstract away the URLs and parameters too. That is a fair summary of the trade. Moya does not remove Alamofire, it adds a layer above it, and layers cost something.

## Licence, maintenance and upgrade cost

Moya is released under the MIT licence, per the repository's License.md and the licence field on the project. MIT is permissive: it allows use in closed-source applications, and the obligation it imposes is preserving the copyright notice and licence text. That is a general description of the licence, not legal advice for your situation.

The upgrade cost is concentrated in major versions. The README points to migration guides under docs for anyone moving to a new major version, and the compatibility table is the document to check first, because it ties Moya, RxMoya, ReactiveMoya, RxSwift, ReactiveSwift and Alamofire versions together in one grid. A Swift version change can force a Moya major version change, which can force a migration guide read.

Maintenance signals in the repository are mixed and worth reading carefully. The last push was on 2026-07-14, and the repository is not archived. The most recent release listed is 15.0.3 from 2022-08-12, which is a long gap between what is published as a release and what is being pushed. The README's claim that the project is under development is a README statement, and the release list is the counterweight to it. If you depend on tagged releases rather than the master branch, plan around that gap.

## Conclusion

Adopt Moya when your app talks to a known set of endpoints and you want the compiler to catch a wrong path or a missing parameter before the app runs. Skip it for a handful of one-off requests, or where you never intend to write request tests. Before committing, verify the Moya version against your Swift version in the compatibility table, check whether the reactive extension you need is RxMoya, ReactiveMoya or CombineMoya, and confirm the migration guide exists for the major version you are leaving.

## FAQ

### What is Moya in Swift?

It is a network abstraction layer written in Swift that sits on top of Alamofire. You define your endpoints as enum cases conforming to TargetType, and Moya handles constructing and issuing the requests.

### How do I install Moya?

The README documents Swift Package Manager, CocoaPods, Carthage and Accio. For SwiftPM you add the package URL with an upToNextMajor version range, and for CocoaPods you add a pod entry such as pod 'Moya', '~> 15.0' and run pod install.

### Which Moya version do I need for my Swift version?

The README's compatibility table maps Swift 5.2 and later to Moya 15.0.0 or above, with RxSwift 6.X, ReactiveSwift 6.X and Alamofire 5.X. Older Swift versions map to earlier Moya majors, down to Moya 7.0.2 through 7.0.4 for Swift 2.3.

### Does Moya work with Combine or RxSwift?

Yes, through separate target dependencies. The README lists RxMoya, ReactiveMoya and CombineMoya, and the CocoaPods subspecs Moya/RxSwift, Moya/ReactiveSwift and Moya/Combine. CombineMoya requires Xcode 11.5.0 or later, and earlier versions need Combine added as a weakly linked framework.

### Is Moya actively maintained?

The repository is not archived and its last push was on 2026-07-14. The most recent release listed is 15.0.3 from 2022-08-12, so the published release and the branch activity do not move at the same pace.

## Sources

- [License: MIT](https://github.com/Moya/Moya/blob/master/LICENSE)
- [Moya/Moya on GitHub](https://github.com/Moya/Moya)
- [Project website](https://moya.github.io)
- [README](https://github.com/Moya/Moya/blob/master/README.md)
- [Releases](https://github.com/Moya/Moya/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/moya-moya
