// Features
Everything you need to run SwiftData-shaped persistence on a real server, against a real database.
01 — Compatibility
The @Model macro, #Predicate, FetchDescriptor, and ModelContext work the way they do in Apple's SwiftData. Model files move between app and server targets without edits.
// Same code works everywhere
let adults = #Predicate<User> {
$0.age >= 18
}
let descriptor = FetchDescriptor(
predicate: adults,
sortBy: [SortDescriptor(propertyName: "name")]
)
let users = try await context.fetchAsync(descriptor)
02 — Backends
PostgreSQL or MySQL in production, in-memory SQLite in tests, and a REST backend that persists through any HTTP API you host — same SwiftData syntax, no direct database connection. Connection pooling and automatic migrations included.
| Backend | Best for |
|---|---|
| PostgreSQL | Production |
| MySQL | Production |
| SQLite | Dev & tests |
| REST | Remote APIs |
@Model
final class Author {
var name: String
@Relationship(deleteRule: .cascade, inverse: \Book.author)
var books: [Book] = []
}
@Model
final class Book {
var title: String
var author: Author?
}
// author.books lazy-loads from the database
03 — Relationships
One-to-many and many-to-many with automatic join tables. Related collections lazy-load on access and refresh after saves.
04 — Vapor
First-class Vapor integration: register your container once and every request gets a context, JSON response helpers, and pagination out of the box.
func routes(_ app: Application) throws {
app.get("users") { req in
try await req.fetchAll(User.self)
}
app.get("users", "page") { req in
try await req.fetchPaginated(User.self, page: 1)
}
}
The documentation covers every API with worked examples.