Nakama Backend Integration for Mobile Games
Nakama—open-source game backend from Heroic Labs. Covers most mobile game server infrastructure: accounts, social features, leaderboards, matchmaking, real-time matches, data storage. Alternative to custom Go/Node.js backend for teams wanting quick mobile game launch without writing server code from scratch.
Client Connection
Nakama SDK available for Unity, Godot, Unreal, and as REST/WebSocket API for native mobile (iOS Swift SDK, Android Kotlin SDK).
On Unity:
var client = new Client("http", "127.0.0.1", 7350, "defaultkey");
var socket = Socket.From(client);
// Authentication via device ID
var session = await client.AuthenticateDeviceAsync(
SystemInfo.deviceUniqueIdentifier,
username: null,
create: true
);
await socket.ConnectAsync(session);
Session auto-refreshes via client.SessionRefreshAsync on token expiry. Store refresh token in PlayerPrefs or Keychain/Keystore—not plain SharedPreferences.
Storage and Player Profile
Nakama Storage Engine—document storage with access control:
var writeObject = new WriteStorageObject {
Collection = "player_data",
Key = "inventory",
Value = JsonWriter.ToJson(inventory),
PermissionRead = 1, // Only owner reads
PermissionWrite = 1 // Only owner writes
};
await client.WriteStorageObjectsAsync(session, new[] { writeObject });
Leaderboard with weekly reset—one-liner via Nakama Console or API. Record result: client.WriteLeaderboardRecordAsync(session, "weekly_score", score: 1500). Get top players with pagination: client.ListLeaderboardRecordsAsync.
Real-Time Matches
Nakama supports two match types: relayed (server relays messages between clients, logic on client) and authoritative (server logic in Lua or TypeScript).
Authoritative match—custom TypeScript module:
const matchInit = (ctx: nkruntime.Context, logger: nkruntime.Logger,
nk: nkruntime.Nakama, params: {[key: string]: string}): {
state: nkruntime.MatchState, tickRate: number, label: string
} => {
return { state: { players: {} }, tickRate: 10, label: "game_room" };
};
const matchLoop = (ctx: nkruntime.Context, logger: nkruntime.Logger,
nk: nkruntime.Nakama, dispatcher: nkruntime.MatchDispatcher,
tick: number, state: nkruntime.MatchState,
messages: nkruntime.MatchMessage[]): nkruntime.MatchState | null => {
// Process incoming messages, update state
for (const msg of messages) {
// validate move, update state
}
dispatcher.broadcastMessage(1, JSON.stringify(state), null, null);
return state;
};
tickRate: 10—10 ticks per second. For turn-based, lower to 1-2.
Matchmaking
var ticket = await client.AddMatchmakerAsync(
session,
query: "+properties.skill:>1200",
minCount: 2,
maxCount: 4,
stringProperties: new Dictionary<string, string> { ["mode"] = "deathmatch" },
numericProperties: new Dictionary<string, double> { ["skill"] = 1500 }
);
socket.ReceivedMatchmakerMatched += matched => {
// Got match, connect
socket.JoinMatchAsync(matched.MatchId);
};
Nakama matchmaker uses Bleve Search style queries. +properties.skill:>1200—find players with skill > 1200. Can add geographic filtering: +properties.region:eu.
Timeline
Basic Nakama integration (authentication, storage, leaderboard): 3-5 days. Full system with authoritative matches, matchmaking, social features: 2-4 weeks. Cost calculated individually.







