Implementing Server-Side Swift

Why we chose Vapor over Kitura

by Finn Hamers

June 30th, 2020

Really the first question that needs to be answered before going into why we chose Vapor is why use Swift on the server at all? The basis of that answer to that is quite simple, we write Swift code all the time and are very familiar with it.

Currently we have a server application written in Ruby, which contains a lot of deprecated functionality and obsolete complexity. Now we are at a time where, because of aggressive app usage growth, this application needs to be out-scaled. When the application was first created Swift on the server was not yet an option, but now that it is, this is the ideal chance for a rewrite. The core functionality does not entail very much so rewriting it is not too much work, and we have a backlog that contains features requiring the application to grow. Because we are much more confident with Swift than Ruby, the initial extra effort would later pay off in maintenance and expansion.

Before starting a rewrite we needed to know if all the functionalities needed were available in Swift. Because server-side Swift is such a young technology, and there are but few developers who have experience with it, this meant creating a proof of concept application. For this I researched the different frameworks for server-side Swift. Because the interest in Swift on the server seems to be growing among iOS developers, this blogs details the main reasons why we chose Vapor for our application.

Results of iOS Developer Community Survey Question 51 Results of iOS Developer Community Survey Question 54

(source: iOS Developer Community Survey 2019)

Reason 1: Database queries and relations

Our server application needs to be able to connect to an external PostgreSQL database, and the objects represented by the database tables ideally need to be represented in code to reduce the need for writing extensive queries.

Representing tables in code is similar in both frameworks and does not take a lot of time and makes use of the Swift Codable protocol. And if you only need basic queries on the database without filtering they are also similar. However, if you often need to add filters to you queries, then Vapor's ORM Fluent outclasses Kitura's Swift-Kuery-ORM. If you want to filter in Kitura you need to either use findAll and then filter the returned objects or write your own function for each kind of filter in an extension of the model. In Vapor it is as easy as creating a query with a filter applied.

To demonstrate, here is the code to get all Books from the database which have a given publication year with Kitura.

Code snippet to get all Book objects in Kitura

Often if you only need a few results you don't want to first query the database for all objects and then filter the result in code, but you want to query with a filter included. Using QueryParams you can create a struct where you add each of the fields you want to filter on. The name must match the name in the Model. This is a step up, but it is still extra work for each filter.

Code snippet to get all books matching a filter in Kitura

In Vapor, adding a filter to a query is done by adding a filter command to the query.

Code snippet to get all books matching a filter in Vapor

If you need a lot of filtering, then creating a struct for each of these filters can become a lot of work, while in Vapor you can just chain commands such as filter and sort on the query. And if this is still not enough, you can always create a raw query on a database connection instead.

Kitura also does not have support for relations between models, though in 2018 they did indicate plans to implement this in the future (see Filtering in Swift-Kuery-ORM). In Vapor this is possible and well-documented. For example, a one-to-many relationship (called a Parent-Child relation in Vapor) between a Notebook and a Page can be defined as follows:

Code snippet of a one-to-many relationship in Vapor

While a many-to-many relationship (called a Sibling relation in Vapor) is a bit more complex, because it includes creating a Pivot, once you understand how they work it is quite easy to add all the relations you need.

Reason 2: Full stack Swift

Kitura has based many of their APIs on standards from the broader web community and their syntax is modeled on Express. Vapor's APIs have been built based on the best practices of Swift code, which also eliminates the need for any non-Swift dependencies.

The heavy use of Futures in Vapor might dissuade people from using Vapor if they are not comfortable writing more functional style code which includes heavy use of methods like map() and flatMap().

Kitura looks more concrete than Vapor, because it exposes its async functionality less in its API, preferring to use closures over map() and flatMap() like methods.

A simple example demonstrates the difference between the two frameworks:

Code snippet of a function to update a database object in Vapor Code snippet of a function to update a database object in Kitura

The Kitura code looks a bit more concrete when you take a quick look at it, if you understand how map() methods work, the Vapor code is easy to understand and more compact. And since we have also used RxSwift, map() methods are not unknown territory to us.

The eliminated need for any non-Swift dependencies and the syntax together makes Vapor stand out to us as the preferred framework.

Reason 3: Community

While Kitura has had IBM behind it from the start, and thus appealed to large enterprises that absolutely need the stability their slower adoption of new technologies and focus on backwards compatibility brought, the community is a lot smaller than the Vapor community.

The following statistics demonstrate the difference in community size and the results of that difference:

Stack Overflow

On Stack Overflow there are just under 600 questions tagged with Vapor, and less than a hundred tagged with Kitura. Note that 600 questions is also a very small amount, compare it for example to Swift with more than 250k questions and Django with 220k questions.

Graph of questions on Stack Overflow tagged Vapor and Kitura respectively

GitHub

From the GitHub statistics you can see that development on Vapor is generally more active, and that the repository for Vapor has more than a thousand forks and over 18k stars, compared to Kitura with just under 500 forks and over 7k stars.

A screenshot of the GitHub Vapor listing A screenshot of the GitHub Kitura listing

iOS Developer Community Survey

And while this data wasn't available at the moment of making the choice, the results form the iOS Developer Community Survey do support the other data, with 87.2% of having deployed to a production environment with Vapor compared to 14.9% with Kitura.

Results of iOS Developer Community Survey Question 52

Importance

A larger community and more active development means that getting an answer to your question or a solution to your problem is more likely, and that possible issues found could be solved quicker.

Reason 4: Documentation

Personally, I have found the Kitura documentation to be lacking. Their documentation exists completely of Guides which show how to do some specific things, but don't explain the syntax, nor do they show best practices, a lot of the Guides tell you to write code in Application.swift, which would make it get cluttered very quickly after adding some functionalities.

When looking into their documentation on databases, models and Swift-Kuery(-ORM) I moved a lot between different sites from IBM and Kitura, instead of having most if not all of the documentation in a central easy to find location.

The Vapor documentation (for 3.0) consist of explanations with examples for each of the official Vapor packages on top of instructions for installation, getting started, and extras such as a style guide. The Vapor documentation very readable and contains database specific examples for i.e. MySQL, PostgreSQL, SQLite.

Both Vapor (here) and Kitura (here) have jazzy generated API documentation for the main repository on top of their other documentation.

Succinct, clear and easy to find centralized documentation makes the development process a lot smoother, with less frustration for the developer(s).

Conclusion

The reasons listed in this post are some of the big reasons we had for choosing Vapor, in the end the decision was made after researching multiple options and getting a feel for the different frameworks. For our purpose Vapor is a good fit, but it might not be for everyone.

The code snippets for Vapor in this article are for Vapor 3, the release of Vapor 4 has come with the release of Swift 5.2. If you want to know about the changes between the versions I recommend reading What's New in Vapor 4 - Swift forums. To keep up to date with releases and changes, you can join the Vapor Discord.

Next Steps

We are currently developing our application using Vapor 4. After we have gone live there will be a follow up blog post on our experiences. Subscribe to our newsletter to not miss any new posts or developments.