January 23rd, 20235 minute read

Deploy server side Swift applications on Vercel

Andrew Barba

Andrew Barba

Vercel is an end-to-end solution for front-end developers to deploy their applications using modern best practices. Connect your project to GitHub, deploy every commit, and get out of the box features like a blazing fast CDN, preview deployments, API routes, local testing environments and so much more. It's a platform that truly get's out of the way and lets engineers focus on their code and applications without worrying about complex infrastructure and processes. As a Swift developer, I'm envious of how easy it is for front-end JavaScript teams to deploy their code to the cloud and start serving their customers. 

That envy ends today - we can now deploy Swift applications like websites, API's and more using the Vercel platform.

The Runtime

Before we start building our application it's important to understand Vercel's architecture and the environment we're going to run our Swift code. Vercel's infrastructure has many layers:

  1. A global CDN for serving static files and caching dynamic routes
  2. Serverless (regional) functions backed by AWS Lambda
  3. Edge (global) functions backed by Cloudflare Workers

We're going to take advantage of Vercel's global CDN and Serverless functions to deploy Swift applications. 

This is all made possible by the fact that Vercel Serverless Functions are backed by AWS Lambda, and Apple recently released the AWS Lambda Runtime for Swift. Lambda is a unique architecture where every incoming request is isolated and given its own container to process the request. This differs from traditional long running servers where a single container will handle many requests. By taking advantage of the Lambda runtime we can pay only for the requests we serve instead of paying 24/7 for a long running server. This architecture also has many benefits when its comes to application resiliancy - will save these details for another blog post.

Build Output API

Vercel prides themselfs on supporting many different frameworks out of the box with zero configuration from the developer. As of this writing, that support does not include Swift applications. Of course supporting every framework and every language is an unreasonable thing for Vercel to do. Instead they have built and documented what they call the Build Output API

The Build Output API is a file-system-based specification for a directory structure that can produce a Vercel deployment.
Framework authors can implement this directory structure as the output of their build command, so that the framework may utilize all of the Vercel platform features.

By taking advantage of this API, we can build a Swift application binary and construct a directory that is fully compliant with their specification - allowing us to deploy our application to Vercel.

Vercel Swift Runtime + SDK

Over the past week I've been working on a Swift package and package plugin that make it trivial to deploy Swift applications to Vercel:

github.com/swift-cloud/Vercel

The goal of this package is twofold:

  1. Provide an SDK that implements Vercel specific API's like their HTTP handling and EdgeConfig functionality.
  2. Provide a Swift package plugin that builds and deploys your Swift applications to Vercel.

import Vercel

Let's start with the SDK. Our goal is to handle incoming HTTP requests and respond with data. This could mean building an API endpoint to trigger a Slack message, send a text to Twilio, or create a payment on Stripe. It even mean building full fledged websites and backend API's that connect to a database like PlanetScale or MongoDB Atlas.

Here's the simplest Swift application we can make:

import Vercel

@main
struct App: RequestHandler {

    func onRequest(_ req: Request, context: Context) async throws -> Response {
        return .status(.ok).send("Hello, Swift")
    }
}

First, we define our application entrypoint as a RequestHandler and mark it with @main. Everytime Vercel receives a request to our application, they will invoke an underlying Lambda container which will execute our onRequest function. The Vercel SDK takes care of parsing the underlying JSON to provide easy to use Request and Response objects as well as other Vercel API like EdgeConfigdictionaries. 

swift package vercel

There's a couple ways we could deploy our code to Vercel:

  1. Locally from our Mac
  2. Via a CI/CD provider like GitHub actions

In both cases we are going to take advantage of the Swift Package Plugin built into the Vercel package:

swift package --disable-sandbox vercel deploy

This plugin will construct the directory compliant with Vercel's Build Output API and then use the Vercel CLI to deploy our application.

Building a Swift Application

To get started building our first Swift application for Vercel, head to the command line and create a new directory for our project:

mkdir VercelApp && cd VercelApp

Next, initialize a new Swift executable application:

swift package init --type executable

Open your project in Xcode and open the Package.swift file to add the Vercel package to your project:

.package(url: "https://github.com/swift-cloud/Vercel", from: "1.2.0")

And then add the platforms array to specify we are building on macOS v12 or later:

platforms: [.macOS(.v12)]

Thats all the setup we need, now we are ready to build our application. In the Sources directory you should see a single folder VercelApp with a main.swift file in the folder. We need to rename this file because we need to define our own entrypoint and cannot rely on main.swift. Rename main.swift to App.swift or anything you'd like. Once renamed, paste in the simple Vercel application:

import Vercel

@main
struct App: RequestHandler {

    func onRequest(_ req: Request, context: Context) async throws -> Response {
        return .status(.ok).send("Hello, Swift")
    }
}

Debugging Locally

One of the most frustrating aspects of server side Swift development is running and debugging your application locally. With this in mind, I wanted to make local debugging as simple as possible, so I built it directly into the Swift package plugin:

swift package --disable-sandbox vercel dev

Running this command will do two things - build and run your Swift application, and start a local Node.js server that proxies requests to the Swift application in the approproate AWS Lambda invoke format. Once running simple open your browser and paste in the local server url:

http://localhost:7676

Deploying your application

We're now ready to deploy our application to Vercel. To get started you'll need a free Vercel account and a few things installed on your Mac:

  1. Vercel CLI
  2. Docker

Back on the command line, lets setup your new Vercel project by running:

vercel link

This will guide you through naming your project and linking your codebase to the Vercel application. You dont't need to customize any options - use the defaults in all prompts.

Once linked, deploy your application using the Swift package plugin:

swift package --disable-sandbox vercel

You'll see your application getting built and the deployed to Vercel. Once complete you'll see your deployment url which will end in vercel.app:

https://swift-starter-kit.vercel.app

Vercel Starter Kit

It's important to understand the architecture behind deploying a Swift application to Vercel, but in order to make the actual development workflow as easy as possible I've open sourced a Vercel Starter Kit which can easily be cloned and for any new project you want to build:

github.com/swift-cloud/vercel-starter-kit

A big advantage of this template is it includes GitHub Actions worflows to deploy every commit to Vercel - just like you would get if you built a JavaScript application directly on the Vercel platform.

What's Next

I've shown you how to deploy a fairly simple Swift application to Vercel but this is truly the tip of the iceberg. You can develop fully baked backend API's that connect to MySQL, Redis, MongoDB and more. You can even develop server-side rendered websites using SwiftUI with our VercelUI package:

github.com/swift-cloud/VercelUI

In order for Swift to succeed as a language it needs to break out of its iOS garden. The more developers use Swift to build backend applications, websites, command line scripts, etc. the better. The Swift runtime for Vercel is just one small step towards Swift's ultimate goal of world domination.

Ready to get started?Request early access.

Join the beta and enjoy 1 click deploys, HTTP/3, globally distributed, 100ms cold starts, custom domains and more...

Get Early Access
App screenshot