Deploy Swift & Vapor to Europe — EU Hosting for Server-Side Swift in 2026
Swift started as Apple's language for iOS and macOS apps. Over the past few years it has quietly become a credible backend language — and for iOS development teams, the case for running your API backend in the same language as your client app is compelling. One language, one type system, shared business logic, and the same async/await concurrency model on both sides of the network.
Vapor 4 is the production-grade web framework that makes this possible. Built entirely in Swift, it uses Swift Concurrency natively — the same async/await and Actor model that iOS 15+ developers already know. This guide shows how to deploy a Vapor application to European infrastructure using sota.io, with EU data residency by default.
Why iOS Teams Are Moving to Server-Side Swift
The shift from iOS developer to full-stack Swift engineer has become significantly easier since Swift 5.9 introduced official Linux support. Here is why this matters:
Shared domain models. Define a User struct once, use it in your iOS app and your Vapor backend. The Swift Package Manager handles the shared code as a local or remote dependency. No JSON schema drift, no manual synchronization between client and server types.
Same concurrency model. Swift Concurrency — async/await, Task, Actor — works identically on Linux and macOS. An iOS engineer who knows how to write concurrent Swift code for UIKit or SwiftUI already understands how to write non-blocking Vapor route handlers.
Performance comparable to Go and Rust. Swift compiles to native machine code. There is no JVM, no garbage collector with stop-the-world pauses, no Python GIL. Vapor benchmarks consistently place it among the top-performing web frameworks, ahead of Node.js and competitive with Go.
GDPR symmetry. European iOS-app startups serving EU users often need their backend in the EU for the same reasons their app collects consent — the data their API handles is personal data subject to DSGVO/GDPR. Running the backend on sota.io closes this compliance loop cleanly.
Vapor 4 vs the Alternatives
The server-side Swift ecosystem has converged around a few frameworks:
Vapor 4 is the mature, full-featured choice. It has a well-developed ORM (Fluent), migrations, queues, authentication, and a large community. Vapor 4 uses Swift Concurrency throughout — async/await route handlers are idiomatic, not an afterthought.
Hummingbird is newer and lighter. It has a smaller API surface, faster startup times, and is better suited for microservices or projects where you want to assemble your own stack. Worth watching if you value minimal dependencies.
Kitura (IBM) is deprecated. IBM ended official support in 2020. Do not start new projects on Kitura.
For most iOS teams moving to the backend, Vapor 4 is the right starting point. It provides enough scaffolding that you are building features, not plumbing.
What You Need
- Vapor 4 application (Swift 5.9+)
- Swift Package Manager (
Package.swift) - Ubuntu 22.04 LTS compatible build (official Swift Linux support)
- A
Dockerfile(we will write one below)
Step 1: Write a Production Dockerfile
Swift on Linux uses multi-stage builds effectively. The builder stage compiles the Swift binary; the runtime stage uses a minimal Debian image with no Swift toolchain:
# Build stage — Swift 5.9 compiler on Ubuntu
FROM swift:5.9-jammy AS build
WORKDIR /app
COPY Package.swift Package.resolved ./
COPY Sources ./Sources
COPY Resources ./Resources
RUN swift build -c release --product App
# Runtime stage — no Swift toolchain, just the compiled binary
FROM debian:bookworm-slim
WORKDIR /app
# Swift runtime libraries required by the binary
RUN apt-get update && apt-get install -y \
libcurl4 \
libxml2 \
&& rm -rf /var/lib/apt/lists/*
COPY --from=build /app/.build/release/App ./App
EXPOSE 8080
ENTRYPOINT ["./App", "serve", "--env", "production", "--hostname", "0.0.0.0", "--port", "8080"]
The resulting image is typically 80–120 MB. The Swift compiler itself is ~500 MB but stays in the build stage only. The runtime binary links against a small set of system libraries available in debian:bookworm-slim.
Step 2: Configure Port and Database
Vapor reads environment variables natively. sota.io injects PORT at runtime:
// Sources/App/entrypoint.swift
import Vapor
@main
struct Entrypoint {
static func main() async throws {
var env = try Environment.detect()
try LoggingSystem.bootstrap(from: &env)
let app = Application(env)
defer { app.shutdown() }
let port = Environment.get("PORT").flatMap(Int.init) ?? 8080
app.http.server.configuration.port = port
app.http.server.configuration.hostname = "0.0.0.0"
try configure(app)
try await app.runFromAsyncMainEntrypoint()
}
}
PostgreSQL via Fluent
When you attach a managed PostgreSQL instance in sota.io, the DATABASE_URL environment variable is injected automatically. Configure Fluent to use it:
// Sources/App/configure.swift
import Vapor
import Fluent
import FluentPostgresDriver
public func configure(_ app: Application) throws {
if let databaseURL = Environment.get("DATABASE_URL") {
try app.databases.use(.postgres(url: databaseURL), as: .psql)
} else {
// Local development fallback
app.databases.use(.postgres(
hostname: "localhost",
username: "vapor",
password: "vapor",
database: "vapor_database"
), as: .psql)
}
// Register migrations
app.migrations.add(CreateUser())
try routes(app)
}
Fluent Migration Example
struct CreateUser: AsyncMigration {
func prepare(on database: Database) async throws {
try await database.schema("users")
.id()
.field("email", .string, .required)
.field("created_at", .datetime)
.unique(on: "email")
.create()
}
func revert(on database: Database) async throws {
try await database.schema("users").delete()
}
}
Run migrations automatically at startup by adding to configure.swift:
try await app.autoMigrate()
Async/Await Route Handler
Vapor 4's native Swift Concurrency support makes route handlers feel identical to iOS async code:
// Sources/App/routes.swift
func routes(_ app: Application) throws {
app.get("users", ":id") { req async throws -> User in
guard let id = req.parameters.get("id", as: UUID.self) else {
throw Abort(.badRequest)
}
guard let user = try await User.find(id, on: req.db) else {
throw Abort(.notFound)
}
return user
}
}
This is standard Swift Concurrency. No callbacks, no completion handlers — exactly the pattern iOS 15+ developers use with URLSession.
Step 3: Deploy to sota.io
npm install -g @sota-io/cli
sota deploy
The CLI packages your Dockerfile, builds the Swift binary on sota.io infrastructure, and returns a live HTTPS URL. The first build takes 3–5 minutes — Swift compilation is slower than Go or Rust but the resulting binary is equally fast at runtime. Subsequent deploys cache the Swift Package Manager dependency resolution step.
For automatic deploys on git push, connect your GitHub repository in the sota.io dashboard.
Performance: Swift vs JVM vs Interpreted Runtimes
Swift compiles to native machine code — the same as Go, Rust, and C++. This gives it a structural performance advantage over JVM and interpreted runtimes:
| Runtime | Cold Start | Memory (idle) | Throughput |
|---|---|---|---|
| Swift / Vapor 4 | ~50ms | ~20 MB | Very high |
| Go / Gin | ~20ms | ~15 MB | Very high |
| Rust / Axum | ~15ms | ~10 MB | Highest |
| JVM / Spring Boot | 3–10s | 200–400 MB | High |
| Node.js / Fastify | ~100ms | ~50 MB | High |
| Python / FastAPI | ~300ms | ~80 MB | Moderate |
For iOS-backend parity, the relevant comparison is not raw throughput — it is operational simplicity. Vapor's startup time and memory footprint are competitive with Go, without requiring a new language for teams already writing Swift.
Comparison: sota.io vs Other Platforms for Swift Backend
| Feature | sota.io | Heroku | Railway | Fly.io |
|---|---|---|---|---|
| Default region | Germany (EU) | US default | US default | Configurable |
| EU data residency | Yes | Needs config | Paid plan | Yes (select regions) |
| GDPR EU DPA | Yes (EU entity) | No (Salesforce/US) | No (US entity) | Limited |
| Swift/Vapor support | Yes (Docker) | Yes (Buildpacks) | Yes (Docker) | Yes (Docker) |
| Managed PostgreSQL | Included | Paid add-on | Paid add-on | Separate |
| Pricing | Flat €9/mo | Usage-based | Usage-based USD | Usage-based USD |
| Cold starts | None | Free tier sleeps | None | None |
Honest comparison: Fly.io has the best global edge network and is genuinely Swift-friendly. sota.io wins when your requirement is specifically EU data residency with an EU-entity DPA — the legal document that satisfies GDPR Article 28 for processing personal data of EU residents.
DACH Verticals for Swift/Vapor
Server-side Swift has particular traction in specific EU market segments:
iOS-app startups (DACH). Teams building consumer-facing iOS apps for Germany, Austria, or Switzerland often need their API in the EU. When the whole stack is Swift, the path from mobile to backend is shorter than any other language combination.
Healthcare apps (DiGA). Germany's Digital Health Applications (DiGA) framework requires that medical apps process patient data within the EU. Swift teams building DiGA-eligible apps need backend infrastructure that satisfies both BfArM technical requirements and GDPR Article 9 (special categories of health data).
Fintech (Austria/Germany). Swift's strong type system and compile-time safety are relevant for transaction processing code where bugs have financial consequences. The FMA (Austria) and BaFin (Germany) require EU data processing for financial data.
What sota.io Gives You
- EU by default — Hetzner Germany, no configuration
- Automatic TLS — Let's Encrypt certificates, auto-renewed
- Managed PostgreSQL 17 —
DATABASE_URLinjected automatically - Flat pricing — €9/month, 2 GB RAM, 50 GB storage, no egress fees
- Native binary performance — Swift compiles to machine code, no runtime overhead
npm install -g @sota-io/cli
sota auth login
sota deploy
Your Vapor app is live in Germany.
See also: Deploy Kotlin & Ktor to Europe · Deploy Go to Europe · Deploy Rust to Europe