swift-valkey
Valkey / Redis
Valkey is an open-source, high-performance key-value store (fork of Redis). The valkey-swift library provides a Swift client with full async/await support, cluster routing, and pub/sub.
Quick Start
Installation
Add to Package.swift:
dependencies: [
.package(url: "https://github.com/valkey-io/valkey-swift.git", from: "1.0.0")
]
Basic Usage
import Valkey
// Connect to single server
let client = try await ValkeyClient.connect(to: .init(host: "localhost", port: 6379))
// Basic operations
try await client.set("key", "value")
let value = try await client.get("key") // Optional<String>
// With expiration
try await client.set("session", sessionData, expiration: .seconds(3600))
// Delete
try await client.del("key")
Cluster Mode
// Connect to cluster
let client = try await ValkeyClient.connect(
to: .cluster([
.init(host: "node1.redis.local", port: 6379),
.init(host: "node2.redis.local", port: 6379),
.init(host: "node3.redis.local", port: 6379)
])
)
// Commands automatically route to correct shard
try await client.set("user:123", userData)
Commands
Strings
// SET with options
try await client.set("key", "value", condition: .nx) // Only if not exists
try await client.set("key", "value", condition: .xx) // Only if exists
try await client.set("key", "value", expiration: .milliseconds(5000))
// GET
let value = try await client.get("key")
// INCR/DECR
let newValue = try await client.incr("counter")
let decreased = try await client.decr("counter")
try await client.incrBy("counter", 10)
Hashes
try await client.hset("user:123", field: "name", value: "Alice")
try await client.hset("user:123", fields: ["name": "Alice", "email": "alice@example.com"])
let name = try await client.hget("user:123", field: "name")
let user = try await client.hgetall("user:123") // [String: String]
Lists
try await client.lpush("queue", "item1", "item2")
try await client.rpush("queue", "item3")
let item = try await client.lpop("queue")
let items = try await client.lrange("queue", start: 0, stop: -1)
Sets
try await client.sadd("tags", "swift", "redis", "backend")
let isMember = try await client.sismember("tags", "swift")
let members = try await client.smembers("tags")
Sorted Sets
try await client.zadd("leaderboard", score: 100, member: "player1")
try await client.zadd("leaderboard", members: [("player2", 200), ("player3", 150)])
let top10 = try await client.zrange("leaderboard", start: 0, stop: 9, withScores: true)
let rank = try await client.zrank("leaderboard", member: "player1")
Pub/Sub
// Subscribe to channels
let subscription = try await client.subscribe(to: ["notifications", "updates"])
// Process messages
for try await message in subscription {
switch message {
case .message(let channel, let payload):
print("Received on \(channel): \(payload)")
case .subscribe(let channel, let count):
print("Subscribed to \(channel)")
}
}
// Publish
try await client.publish("notifications", message: "Hello subscribers!")
// Pattern subscribe
let patternSub = try await client.psubscribe(to: ["user:*", "event:*"])
Transactions
// MULTI/EXEC transaction
let results = try await client.transaction(
SET("key1", "value1"),
SET("key2", "value2"),
GET("key1")
)
// Results is tuple: (Result<String?, Error>, Result<String?, Error>, Result<String?, Error>)
Pipelining
// Execute multiple commands in single round-trip
let (setResult, getResult, incrResult) = try await client.execute(
SET("key", "value"),
GET("key"),
INCR("counter")
)
Cluster Routing
Commands are automatically routed to the correct shard based on key hash slots:
// Keys with same hash tag go to same shard
try await client.set("{user:123}:profile", profileData)
try await client.set("{user:123}:settings", settingsData)
// Both keys route to same shard due to {user:123} hash tag
Connection Configuration
let config = ValkeyClient.Configuration(
endpoints: .single(.init(host: "localhost", port: 6379)),
password: "secret",
database: 0,
connectionTimeout: .seconds(5),
commandTimeout: .seconds(30),
tls: .require(.makeClientConfiguration())
)
let client = try await ValkeyClient.connect(configuration: config)
Error Handling
do {
let value = try await client.get("key")
} catch let error as ValkeyClientError {
switch error {
case .connectionClosed:
// Reconnect logic
case .timeout:
// Retry logic
case .serverError(let message):
print("Server error: \(message)")
}
}
Reference Files
Load these files as needed for specific topics:
references/valkey-patterns.md- Command protocol pattern, RESP encoding/decoding, cluster routing with hash slots, subscription management, transaction patterns, connection pool integration, module extensions
More from joannis/claude-skills
hummingbird
Expert guidance on Hummingbird 2 web framework. Use when developers mention: (1) Hummingbird, HB, or Hummingbird 2, (2) Swift web server or HTTP server, (3) server-side Swift routing or middleware, (4) building REST APIs in Swift, (5) RequestContext or ChildRequestContext, (6) HummingbirdAuth or authentication middleware, (7) HummingbirdWebSocket, (8) HummingbirdFluent or database integration, (9) ResponseGenerator or EditedResponse.
26swift-nio
Expert guidance on SwiftNIO best practices, patterns, and implementation. Use when developers mention: (1) SwiftNIO, NIO, ByteBuffer, Channel, ChannelPipeline, ChannelHandler, EventLoop, NIOAsyncChannel, or NIOFileSystem, (2) EventLoopFuture, ServerBootstrap, or DatagramBootstrap, (3) TCP/UDP server or client implementation, (4) ByteToMessageDecoder or wire protocol codecs, (5) binary protocol parsing or serialization, (6) blocking the event loop issues.
26swift-library-design
Expert guidance on Swift library and framework design. Use when developers mention: (1) designing a Swift library or framework, (2) public API design patterns, (3) protocol-oriented architecture or associated types, (4) result builders or DSL design, (5) performance optimization for libraries, (6) @inlinable or @usableFromInline, (7) noncopyable types for APIs, (8) progressive disclosure in API design, (9) ResponseGenerator or builder patterns.
25wendy
Expert guidance on building and deploying apps to WendyOS edge devices. Use when developers mention: (1) Wendy or WendyOS, (2) wendy CLI commands, (3) wendy.json or entitlements, (4) deploying apps to edge devices, (5) remote debugging Swift on ARM64, (6) NVIDIA Jetson or Raspberry Pi apps, (7) cross-compiling Swift for ARM64.
24database-driver-design
Expert guidance on building Swift database client libraries. Use when developers mention: (1) building a database driver, (2) wire protocol implementation, (3) connection pooling design, (4) state machines for protocol handling, (5) NIO channel handlers for databases, (6) backpressure in result streaming, (7) actor executor alignment with NIO.
24swift
Expert guidance on Swift best practices, patterns, and implementation. Use when developers mention: (1) Swift configuration or environment variables, (2) swift-log or logging patterns, (3) OpenTelemetry or swift-otel, (4) Swift Testing framework or @Test macro, (5) Foundation avoidance or cross-platform Swift, (6) platform-specific code organization, (7) Span or memory safety patterns, (8) non-copyable types (~Copyable), (9) API design patterns or access modifiers.
23