Week 1

Before we get into it, I’d like to give a shout out to @0xTim for writing an awesome article on the high level changes between Vapor 2 and Vapor 3. If that sounds like your jam, give it a read! They’ll be keeping it up to date all the way up to the official release of Vapor 3 so feel free to check back every once in a while.


Vapor 3 Release Schedule Announced!

We’re looking at the first tagged Beta release on February 9th, the first stable release on February 23rd, and Vapor 3.0 sometime in mid March to coincide with the Swift 4.1 release. In addition, Vapor 3 relies on the Swift 4.1 beta as of this week, so go get it installed!


New Features

CHTTP Refactor


PostgreSQL Support for DB Usernames and Passwords

Previously, you were just fine as long as you were using the default PostgreSQL setup, but if you wanted to password protect your DB, you were out of luck. Well that is no more! Protect away my friends.


Under The Hood

CHTTP Refactor


SocketSink and SocketSource Refactor


Community Contributions

Community contributions is where we take the time to highlight community members who saw an issue and put in the work to fix it. Check out what these folks are doing, and maybe get yourself on this list next week! 😀

Changed query comparison operators paths to KeyPath

@calebkleveter enabled Vapor users to use both constant and variable model properties in query filter comparisons; previously only non-constant properties were usable in this context. (3 Lines of Code)


Allows users to access password protected DBs with PostgreSQLDatabaseConfig

While the core Vapor team put in the work to access passworded DBs with the PostgreSQL driver, @MihaelIsaev drove it home by exposing that functionality to Vapor’s users. (5 Lines of Code)



Vapor Beats Go’s Gin and Node’s Express in Requests per Second

It’s an unofficial benchmark run by @tanner0101, but here are the numbers!

That’s over 91% efficiency we’re seeing from Vapor! Nice! Huge gains were made via lazy header parsing. Since most of the time between 0 and 1 headers need to be accessed, header data is copied into a buffer and retrieved only when requested. Another big gain resulted from utilizing Copy on Write wrappers, which let you fine tune when data actually gets copied. To quote Tanner,

Our HTTPRequest is a struct, but since the headers are in a CoW wrapper, the request can be copied and mutated as much as desired without copying the headers. The headers will only copy if they detect belonging to two distinct HTTPRequests and one of them is trying to mutate their contents. If no one tries to mutate the headers, it’s possible you could have hundreds of HTTP requests all sharing the same header storage in memory. This makes Swift really special because it’s a case where being higher level than C can actually yield more performance than is realistically possible in C.

That’s pretty awesome if you ask me 🏁


Routing in Vapor 3, Part 1: Basic Routing

Routing is at the heart of web frameworks, and it’s easy with Vapor. This tutorial will teach you what you need to know to get started.


How to implement Image-Upload [Vapor 2]

In this tutorial, you’ll learn how to upload an image for a user and save it to the disk as well as how to serve it back as a profile picture. This will be core for anyone wanting to set up a site with user generated content.



This week we’re highlighting Vapor’s content API which you’ll be using in the vast majority of your projects. By taking advantage of Swift’s Codable protocol, Vapor is able to automatically map JSON to Swift objects and back again. Doing so affords you the type safety you not only deserve, but need right now.

In the below example, if you sent a POST request with the body


Vapor would automatically provide a LoginRequest instance with those values!

struct LoginRequest: Content {
  var email: String
  var password: String

router.post("login") { req -> Future<Response> in
  return try req.content.decode(LoginRequest.self).map(to: Response.self) { loginRequest in
      print(loginRequest.email) // user@vapor.codes
      print(loginRequest.password) // don't look!
      return req.makeResponse()


@gwynne @Cellane @calebkleveter