Nakama Game Server Setup: 13 Steps, 90 Min [2026]

Every studio shipping a multiplayer game eventually asks the same question: pay a managed backend provider by the player, or run the thing yourself. Nakama, the open-source game server built by Heroic Labs, is the answer for teams that want authentication, matchmaking, leaderboards, chat, and a scriptable server runtime without a recurring per-CCU bill. As of October 1, 2026, the project sits at version 3.41.0, released September 18, 2026, and the GitHub repository shows 13,456 stars and 1,503 forks — numbers that have kept climbing since Heroic Labs open-sourced the server under Apache 2.0 back in 2017.

This tutorial walks through a full, working Nakama deployment: provisioning a cloud server, running Nakama and CockroachDB in Docker Compose, wiring up a game client SDK, putting TLS and a firewall in front of the stack, and hardening the setup with backups and monitoring. By the end you will have a production-ready game backend running on infrastructure you control, plus the troubleshooting notes to get through the parts that trip up most first-time deployments.

None of this requires a dedicated backend team. A solo developer or a small studio can realistically get the stack below running on a single cloud VM in under two hours, and the same Docker Compose foundation scales up to a multi-node cluster later without a rewrite. That’s the real argument for Nakama over building a custom backend from scratch: you get authentication, real-time networking, and persistence on day one, and you only take on the operational complexity of scaling it once you actually have the player count that justifies it.

Google · Preferred Sources

Don't miss new tech stories on Google

Add Tech Insider once in the Google app and our stories appear in your news suggestions.

Add Now

What Is Nakama, and Why Self-Host a Game Backend in 2026?

Nakama is a scalable, open-source game server written in Go. It bundles the services most multiplayer games need into a single binary: device and social authentication, a storage engine for player data, real-time chat and parties, a matchmaker, leaderboards and tournaments, in-app purchase validation, and a server runtime that lets you write custom logic in TypeScript, Lua, or Go. The official GitHub repository describes it as a backend for “multiplayer, matchmaking, leaderboards, chat, and social features for games,” and the project has been actively maintained since its first commit in January 2017.

The appeal of self-hosting comes down to three things: cost, control, and data residency. A managed backend-as-a-service typically charges per monthly active user, per concurrent connection, or per compute-hour once you exceed a free tier. Nakama has no such metering built in — you pay only for the cloud compute and database storage you provision. That also means you decide where player data physically lives, which matters for studios operating under GDPR or similar regional data rules. The trade-off is that you own the operations: patching, scaling, backups, and incident response all fall on your team rather than a vendor’s SRE group.

Heroic Labs also sells a managed version of the same software, Heroic Cloud, for teams that want the open-source feature set without running servers themselves. We cover that trade-off, along with how Nakama stacks up against Microsoft’s PlayFab and the newer SpacetimeDB engine, in our SpacetimeDB vs PlayFab vs Nakama comparison. If you’ve already decided a managed server fleet fits your project better, our PlayFab Multiplayer Servers setup guide covers that path step by step.

Under the hood, Nakama’s storage engine works like a lightweight document database scoped to collections, keys, and user ownership, which is enough for inventories, profiles, and save data without standing up a separate NoSQL service. The leaderboard and tournament systems support both ascending and descending score ordering, scheduled resets, and multiple scoring operators (best, set, increment, decrement), which covers most competitive and cooperative scoring patterns out of the box. Groups and parties handle guild-style structures and temporary squad formation, and the built-in chat system supports direct messages, group channels, and room-based chat without any extra service. None of that requires custom code — it’s all reachable through the client SDK the moment the server is running, which is a big part of why teams choose Nakama over wiring together several smaller services themselves.

Prerequisites and System Requirements

You don’t need a large team or a big budget to follow this tutorial, but you do need a few pieces in place before Step 1. Here’s what to have ready:

RequirementMinimum Version / SpecNotes
Cloud VM or bare-metal host2 vCPU / 4 GB RAM (dev), 4 vCPU / 8 GB RAM (small production)DigitalOcean, Hetzner Cloud, AWS EC2, or GCP Compute Engine all work; Heroic Labs publishes an official DigitalOcean deployment guide
Operating systemUbuntu 24.04 LTS or Debian 12Any Linux distribution with a supported Docker Engine build works
Docker Engine24.0 or laterInstalled via Docker’s official install script
Docker ComposeCompose v2 pluginShips with modern Docker Engine installs; verify with docker compose version
DatabaseCockroachDB or any PostgreSQL wire-compatible serverThe official Docker Compose quickstart bundles CockroachDB as a container
Domain nameAny registrarNeeded for a TLS certificate in Step 12
Game client engine (optional)Unity 2022 LTS+, Unreal Engine 5, Godot 4, or similarOnly needed if you plan to connect a real client, per Step 10

Nakama reserves three ports by default, documented in Heroic Labs’ official configuration reference, and you’ll see them throughout this guide: 7349 for the gRPC API, 7350 for the client-facing HTTP/WebSocket gateway, and 7351 for the Nakama Console admin UI. CockroachDB adds two more — 26257 for SQL and 8080 for its own admin dashboard — both of which should never be exposed to the public internet in a production setup.

It also helps to decide upfront which language you’ll use for server-side logic, since that choice shapes your local development environment before you write a single line of custom code. The next section breaks down the three options.

Choosing a Server Runtime Language: TypeScript, Lua, or Go

Nakama’s server runtime is where you put logic you don’t trust the client to run honestly — granting currency, validating a purchase receipt, resolving a match outcome, or enforcing a matchmaking rule. You get three choices for writing that logic, and the right one depends on your team’s existing stack more than any performance difference.

TypeScript is usually the easiest on-ramp for teams coming from Unity, web, or mobile backgrounds. It runs on a JavaScript engine embedded in the Nakama binary, compiles ahead of time into a single bundle, and gives you the npm ecosystem for things like JSON validation or date handling. The trade-off is a small performance tax compared to compiled Go, which rarely matters for RPC handlers and matchmaker hooks but can matter for very hot code paths called on every tick of a real-time match.

Lua was Nakama’s original scripting language and is still fully supported. It’s lightweight and fast to iterate on, and plenty of production games still run Lua modules written years ago. New projects starting from scratch in 2026 are more likely to reach for TypeScript or Go simply because tooling, editor support, and hiring are easier, but Lua remains a legitimate choice if your team already has Lua experience from other game engines.

Go modules compile directly into the Nakama binary at build time rather than loading as a separate bundle, which makes them the fastest option and gives you access to the full Go standard library and any Go package you need. The cost is a heavier build process — you compile a custom Nakama binary rather than just dropping a script file into a mounted volume — which makes Go modules better suited to teams that already have a Go build pipeline than to a quick prototype. For the lobby example in this tutorial, TypeScript is the pragmatic default, and it’s what the complete working project later in this guide uses.

Nakama vs PlayFab vs SpacetimeDB: Where Self-Hosting Actually Fits

Before committing to a self-hosted deployment, it’s worth confirming Nakama is the right tool for your project. The three backends solve overlapping problems with different operating models.

BackendHosting modelServer logic languagePricing modelDatabase dependency
Nakama (self-hosted)You run it — any cloud or bare metalTypeScript, Lua, or GoFree and open source; you pay only for infrastructureCockroachDB or PostgreSQL-wire-compatible
Heroic Cloud (managed Nakama)Heroic Labs-managed dedicated capacityTypeScript, Lua, or GoCapacity-based; Nakama Enterprise carries no DAU/MAU/CCU cap according to Heroic LabsManaged by Heroic Labs
Microsoft Azure PlayFabFully managed on AzureCloudScript (JavaScript) or server SDKsUsage-based tiers plus Multiplayer Server compute hoursManaged, no self-hosting option
SpacetimeDBSelf-hosted or managed cloudRust or C# modules compiled to WASMFree and open source core; hosted tier availableBuilt-in relational database engine

If your game needs a dedicated, authoritative simulation server that scales per-match rather than per-persistent-service, a fleet orchestrator like Amazon GameLift or a Kubernetes-based setup such as Agones on Kubernetes is a better fit than Nakama alone. Nakama shines for the “always-on” layer: accounts, social features, matchmaking, and persistent player state that sits in front of whatever simulation server you choose. Some studios run Nakama for the social layer and a separate authoritative server — built with something like Colyseus — for real-time gameplay simulation.

Step 1-3: Provision a Cloud Server and Install Docker

Step 1: Spin up a VM. Create a new instance with at least 2 vCPUs and 4 GB of RAM on your cloud provider of choice. Heroic Labs’ own deployment documentation walks through DigitalOcean specifically, but the steps below are provider-agnostic — the same commands work on Hetzner, AWS EC2, or GCP Compute Engine. Pick a region close to your expected player base to keep round-trip latency low.

Step 2: Connect and update the system. SSH into the new instance and bring the package list up to date before installing anything else.

ssh root@your-server-ip
apt update && apt upgrade -y

Step 3: Install Docker Engine and the Compose plugin. Docker’s official convenience script handles both in one pass and is the fastest way to get a working install on a fresh Ubuntu or Debian host.

curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
usermod -aG docker $USER
newgrp docker
docker --version
docker compose version

You should see Docker Engine report version 24 or later and Compose report a v2.x build. If either command errors out, log out and back in so your shell picks up the new docker group membership before continuing.

Step 4-6: Configure Nakama and CockroachDB with Docker Compose

Step 4: Create a project directory. Keep the Compose file and any custom server modules in one place so backups and upgrades stay simple.

mkdir -p ~/nakama-stack/data/modules
cd ~/nakama-stack

Step 5 and 6: Write the Compose file. The following docker-compose.yml defines two services — CockroachDB as the database and Nakama as the game server — following the pattern in Heroic Labs’ own Docker quickstart. Pin the Nakama image tag to a specific version, using the official heroiclabs/nakama image on Docker Hub, rather than latest so an upstream release doesn’t change your running stack without warning.

version: "3.8"
services:
  cockroachdb:
    image: cockroachdb/cockroach:latest-v24.3
    command: start-single-node --insecure --store=attrs=ssd,path=/var/lib/cockroach/
    restart: unless-stopped
    volumes:
      - cockroach-data:/var/lib/cockroach
    expose:
      - "8080"
      - "26257"

  nakama:
    image: heroiclabs/nakama:3.41.0
    entrypoint:
      - "/bin/sh"
      - "-ecx"
      - >
        /nakama/nakama migrate up --database.address root@cockroachdb:26257 &&
        exec /nakama/nakama --name nakama1
        --database.address root@cockroachdb:26257
        --logger.level INFO
        --session.token_expiry_sec 7200
        --console.port 7351
        --socket.port 7350
    restart: unless-stopped
    depends_on:
      - cockroachdb
    volumes:
      - ./data/modules:/nakama/data/modules
    ports:
      - "7349:7349"
      - "7350:7350"
      - "7351:7351"
    healthcheck:
      test: ["CMD", "/nakama/nakama", "healthcheck"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  cockroach-data:

Note the migrate up command baked into the Nakama entrypoint. Nakama requires its database schema to be migrated before the server process starts, and running it inline on every container start is safe — the migration is idempotent and simply skips already-applied changes on subsequent restarts.

Step 7-9: Launch the Stack and Verify the Console

Step 7: Start the containers.

docker compose up -d
docker compose logs -f nakama

Watch the logs for a line confirming the migration completed and the server is listening on its configured ports. A healthy startup typically takes under 15 seconds once the images are pulled.

Step 8: Confirm the migration applied. You can check CockroachDB directly to see the Nakama schema in place.

docker compose exec cockroachdb ./cockroach sql --insecure --execute="SHOW DATABASES;"

Expected output includes a nakama database alongside CockroachDB’s internal system databases:

  database_name
-----------------
  defaultdb
  nakama
  postgres
  system
(4 rows)

Step 9: Open the Nakama Console. Point a browser at http://your-server-ip:7351. You should land on the Nakama Console login screen. The default credentials in a fresh install are the username and password defined (or left at their defaults) in your Compose command flags — change these immediately if you exposed port 7351 to the public internet, which Step 12 addresses by routing console access through an authenticated reverse proxy instead. A quick health check from the command line confirms the client-facing API is responding:

curl -i http://localhost:7350/
HTTP/1.1 404 Not Found
Content-Type: application/json

{"code":5,"message":"Not Found"}

That 404 is expected — the root path isn’t a defined route, but a structured JSON error response (rather than a connection timeout) confirms Nakama’s HTTP gateway is up and listening.

Step 10-11: Connect a Game Client SDK

Step 10: Install a client SDK. Nakama publishes official client libraries for Unity/.NET, Unreal C++, JavaScript, Dart (Flutter), Godot 3, Godot 4, Swift, Java/Android, and both the C++ and JavaScript flavors of Cocos2d-x. For a Unity project, add the Nakama package through the Unity Package Manager using the git URL from the official repository, or import the .unitypackage release directly from the project’s GitHub releases page.

Step 11: Authenticate a test user. The snippet below connects to your server and authenticates a player using their device ID — the simplest authentication method for a first test, with email, Google, Apple, Facebook, Steam, and custom authentication all supported for production use.

using Nakama;
using UnityEngine;

public class NakamaConnector : MonoBehaviour
{
    async void Start()
    {
        var client = new Client("http", "your-server-ip", 7350, "defaultkey");
        var deviceId = SystemInfo.deviceUniqueIdentifier;

        var session = await client.AuthenticateDeviceAsync(deviceId);
        Debug.Log("Authenticated user ID: " + session.UserId);

        var socket = client.NewSocket();
        await socket.ConnectAsync(session);
        Debug.Log("Realtime socket connected.");
    }
}

Run the scene and check the console output. A successful run prints a UUID-formatted user ID followed by the socket connection confirmation — proof that authentication, the HTTP API, and the real-time WebSocket layer are all reachable from a real client.

Step 12: Add TLS, a Reverse Proxy, and Firewall Rules

Running game traffic over plain HTTP means session tokens travel in the clear. Before pointing any real players at the server, put a reverse proxy in front of Nakama’s client port and let it handle certificate issuance. Caddy is a reasonable choice here because it automates Let’s Encrypt without extra configuration.

your-domain.com {
    reverse_proxy /* nakama:7350
    encode gzip
}

Point your domain’s A record at the server’s public IP before starting Caddy, since Let’s Encrypt’s HTTP-01 challenge needs port 80 reachable from the public internet to issue a certificate. Then lock down the firewall so only the ports you actually need to expose are open — everything else, especially CockroachDB’s SQL and admin ports, should stay internal.

ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw deny 26257/tcp
ufw deny 8080/tcp
ufw deny 7351/tcp
ufw enable

Notice that port 7351 (the Nakama Console) is explicitly denied from the public internet in this rule set. Access it instead through an SSH tunnel (ssh -L 7351:localhost:7351 root@your-server-ip) or route it through the reverse proxy with its own authentication layer — never leave the admin console reachable on the open internet.

Step 13: Harden for Production — Backups, Monitoring, and CI/CD

A single-node CockroachDB container, as configured above, is fine for development but has no built-in redundancy. For production, schedule regular backups to object storage so a lost disk doesn’t mean lost player data.

docker compose exec cockroachdb ./cockroach sql --insecure --execute="
BACKUP DATABASE nakama INTO 's3://your-backup-bucket/nakama?AWS_ACCESS_KEY_ID=KEY&AWS_SECRET_ACCESS_KEY=SECRET';"

Wrap that command in a cron job that runs nightly, and store the credentials outside the repository using environment variables or a secrets manager. For monitoring, Nakama exposes a Prometheus-compatible metrics endpoint that you can scrape alongside standard host-level metrics (CPU, memory, disk I/O) to catch capacity problems before players notice them. For server-side game logic, keep your TypeScript or Go runtime modules in version control and build a small CI pipeline that runs tests, builds the module bundle, and redeploys the Nakama container — mirroring how you’d already handle deploys for any other backend service.

Common Pitfalls When Deploying Nakama

  • Running Nakama and CockroachDB on a single-core VM. Both processes compete for the same core during matchmaker ticks and database writes, producing latency spikes that look like a Nakama bug but are actually a resource constraint. Budget at least 2 vCPUs even for testing.
  • Skipping the migration step. If you write a custom entrypoint and forget to run migrate up before starting the server, Nakama will fail to boot with schema errors. Keep the migration chained into the startup command as shown in Step 6.
  • Exposing CockroachDB’s admin UI or SQL port publicly. Ports 8080 and 26257 should never face the open internet. Leaving them open is one of the more common misconfigurations in quick Docker Compose tutorials copied without the firewall step.
  • Leaving the console on default credentials. The Nakama Console has full read/write access to player data and server configuration. Change default admin credentials immediately after your first login.
  • Pinning the image to :latest instead of a version tag. A routine docker compose pull can silently jump you several minor versions and change default behavior. Always pin to an explicit tag like 3.41.0 and upgrade deliberately.
  • Serving game traffic over plain HTTP in production. Session tokens and player data are sent unencrypted without TLS. Don’t skip Step 12 even for a “soft launch.”
  • Treating a single CockroachDB node as production-grade. A single-node deployment has no replication; a disk failure takes your entire player database with it. Scale to a multi-node CockroachDB cluster or rely on automated backups at minimum before launch.
  • Mounting the modules directory with the wrong path. A typo in the Compose volume mapping means Nakama starts successfully but silently never loads your custom RPC handlers, which looks like a bug in your TypeScript code when it’s actually a path mismatch. Double-check the container-side path matches exactly what your InitModule registration expects.
  • Forgetting to test client reconnection behavior. A dropped WebSocket during a rolling deploy or a brief network blip will happen eventually in production. If your client treats that as a fatal error instead of reconnecting, players get kicked out of matches for reasons that have nothing to do with your game logic.

Troubleshooting Nakama Deployment Issues

SymptomLikely CauseFix
“connection refused” on port 7350 from a clientFirewall blocking the port, or container not startedCheck docker compose ps and confirm the port is allowed through ufw status
Container restarts in a loop immediately after startupMigration failed or database unreachableRun docker compose logs cockroachdb and confirm the database container is healthy before Nakama starts
Console login page loads but credentials are rejectedWrong default credentials or a stale browser cache from a previous deploymentClear cookies for the console URL and confirm the credentials set in your Compose command flags
Client SDK throws an “Unavailable” RPC errorClient pointed at the wrong port or scheme (ws vs http)Confirm the client uses the HTTP/WebSocket gateway port (7350), not the gRPC port (7349), unless you specifically configured gRPC
CockroachDB logs show “node is not bootstrapped”The single-node start flag wasn’t applied correctly, or the data volume is corruptedRemove the volume and restart with start-single-node explicitly in the command
High memory usage leads to an OOM killVM undersized for the configured connection poolResize to at least 4 GB RAM, or lower --database.conn_max_open in the Nakama startup flags
Let’s Encrypt certificate fails to issue via CaddyDNS not yet propagated, or port 80 blocked by a cloud firewallConfirm the A record resolves and port 80 is open before starting Caddy
Matchmaker never returns a match in local testingOnly one test client connected, or the matchmaker query filters are too strictConnect at least two test sessions and loosen matchmaker criteria for a local sanity check
TypeScript server runtime module fails to loadBuild output missing or placed outside the mounted modules directoryConfirm the compiled bundle lands in ./data/modules, which is the volume mounted into the container in Step 6

Load Testing Your Nakama Deployment Before Launch

A deployment that handles one Unity test client cleanly can still fall over at 500 concurrent players if you haven’t tested for it. Before any real launch, run a load test that simulates realistic client behavior rather than just hammering a single endpoint, since Nakama’s resource usage differs a lot between simple leaderboard reads, real-time match traffic, and matchmaker churn.

A practical approach is to write a small headless test client using the same SDK your game uses — the Node.js or JavaScript client works well for this since it’s easy to script — and spin up dozens or hundreds of instances from a separate machine than the one running Nakama, so your load generator doesn’t compete with the server for CPU. Have each simulated client authenticate, join the matchmaker, send a handful of real-time messages, and write a leaderboard score, then watch four things on the server side: CPU and memory on the Nakama container, query latency on CockroachDB, the number of open WebSocket connections, and whether the matchmaker is actually pairing clients within an acceptable time window rather than timing out.

Run the test again after any change to VM size, database topology, or server runtime code, and keep a simple spreadsheet of “concurrent clients vs. CPU usage” over time. That gives you an early warning well before a real spike in players catches you off guard, and it turns the “how many players can this handle” question from a guess into a number you’ve actually measured on your own infrastructure.

Advanced Tips: Scaling Nakama Beyond a Single Node

Once a single-node setup proves the concept, scaling Nakama horizontally is mostly a matter of running multiple Nakama containers against the same CockroachDB cluster, sitting behind a load balancer. Because Nakama is designed to be stateless at the application layer — session and match state lives in the database and in-memory match handlers — you can add nodes as player count grows, as long as your load balancer supports sticky routing for WebSocket connections so a player’s real-time socket doesn’t bounce between nodes mid-session.

For the database layer, move from the single-node CockroachDB container to a proper multi-node cluster (three nodes minimum for quorum) once you’re past the prototype stage. CockroachDB handles the replication and failover automatically, which is the main reason Heroic Labs chose it as Nakama’s reference database over plain PostgreSQL. If your team already standardizes on AWS infrastructure, running the database tier through a managed Postgres-compatible service and connecting Nakama to it is also a supported path, since Nakama only requires PostgreSQL wire compatibility rather than CockroachDB specifically.

On the operations side, wire Nakama’s Prometheus metrics endpoint into whatever observability stack you already run, and set alerts on connection counts, match creation rate, and database query latency rather than just CPU and memory. Those application-level signals catch matchmaking or storage problems well before the host-level metrics show anything unusual.

Deployment rollout strategy matters once you have more than one Nakama node. Rolling deploys — updating one node at a time while the load balancer keeps routing to the others — avoid a full outage during a version bump, but only work cleanly if your client SDK handles a dropped WebSocket connection by reconnecting automatically rather than treating it as a fatal error. Test that reconnect path specifically; it’s easy to build a client that works fine against a single, never-restarted dev server and then falls apart the first time a production node gets recycled mid-session. For teams running a broader microservices stack already, placing Nakama behind the same ingress and service mesh you use elsewhere, rather than treating it as a special case, usually pays off once you have more than a couple of nodes to manage.

Nakama Self-Hosted Cost vs Heroic Cloud: What to Budget

The appeal of self-hosting is obvious on paper — the software is free — but it’s worth budgeting the real infrastructure cost before committing a production launch to it.

ApproachTypical monthly costWhat’s included
Self-hosted, single VM (dev/small production)Roughly the cost of a 4 vCPU / 8 GB cloud VM, typically well under $100/month on providers like Hetzner or DigitalOceanNakama + CockroachDB on one host; you handle backups, TLS, and monitoring yourself
Self-hosted, multi-node production clusterScales with node count and database cluster size — several hundred dollars per month is typical for a small live gameLoad-balanced Nakama nodes plus a replicated CockroachDB cluster
Heroic Cloud (managed)Capacity-based pricing starting in the hundreds of dollars per month, according to third-party cost comparisons published in 2026Dedicated hardware, managed database, CI for server modules, backups, monitoring, and support handled by Heroic Labs

Heroic Labs’ own pricing page doesn’t publish a simple public rate card for Heroic Cloud — pricing is capacity-based and typically arranged directly with their sales team, with Nakama Enterprise carrying no stated DAU, MAU, or CCU limit. Third-party comparison sites in 2026 have cited figures ranging from roughly $600 to $6,000 a month depending on the support tier and allocated capacity, though those numbers should be treated as indicative rather than an official rate card. For a side project or an early-access launch, the self-hosted single-VM path above is almost always the cheaper starting point; the economics shift toward a managed option once you need guaranteed uptime SLAs and don’t want to staff the on-call rotation yourself.

Complete Working Project: A Minimal Multiplayer Lobby Backend

Putting the pieces from this tutorial together gives you a working project with three files. First, the docker-compose.yml from Step 6, unchanged. Second, a minimal TypeScript server runtime module that registers a custom RPC function — the kind of server-authoritative logic you can’t safely run on the client.

// data/modules/main.ts
function rpcCreateLobby(
  ctx: nkruntime.Context,
  logger: nkruntime.Logger,
  nk: nkruntime.Nakama,
  payload: string
): string {
  const lobbyId = nk.uuidv4();
  logger.info("Created lobby %s for user %s", lobbyId, ctx.userId);
  return JSON.stringify({ lobbyId: lobbyId });
}

let InitModule: nkruntime.InitModule = function (
  ctx: nkruntime.Context,
  logger: nkruntime.Logger,
  nk: nkruntime.Nakama,
  initializer: nkruntime.Initializer
) {
  initializer.registerRpc("create_lobby", rpcCreateLobby);
  logger.info("Lobby module loaded.");
};

Third, the client-side call from Step 11’s Unity project, extended to invoke that custom RPC after authentication:

var response = await client.RpcAsync(session, "create_lobby", "{}");
Debug.Log("Lobby created: " + response.Payload);

Build the TypeScript module into the bundle format Nakama expects, drop it into ./data/modules, restart the Nakama container, and you have an authenticated client talking to a custom, server-authoritative RPC — the same pattern you’d extend to matchmaking hooks, leaderboard writes, or in-app purchase validation for a real game.

Frequently Asked Questions

Is Nakama really free to self-host?

Yes. Nakama is released under the Apache 2.0 license and the server binary itself carries no licensing fee. You only pay for the infrastructure — compute, storage, and bandwidth — that you provision to run it, plus optional Heroic Cloud or Heroic Labs enterprise support if you choose a managed or supported path later.

Do I have to use CockroachDB, or can I use regular PostgreSQL?

Nakama’s requirement is a PostgreSQL wire-compatible database, and CockroachDB is what Heroic Labs bundles in its official quickstart and recommends for production due to its built-in replication. A standard PostgreSQL server also works for development and smaller deployments, provided it meets the wire-compatibility requirement Nakama checks on startup.

What game engines can connect to a self-hosted Nakama server?

Heroic Labs publishes official client SDKs for Unity/.NET, Unreal Engine (C++), Godot 3 and 4, JavaScript, Dart/Flutter, Swift, Java/Android, and Cocos2d-x in both its C++ and JavaScript variants. Any engine capable of making HTTP and WebSocket calls can also integrate with Nakama’s REST API directly, even without an official SDK.

How many players can a single self-hosted Nakama instance handle?

It depends heavily on what features you’re using (real-time matches are heavier than simple leaderboard calls) and the hardware behind it. A single modest VM, following the sizing in this tutorial, comfortably handles development and small early-access player bases; beyond that, horizontal scaling with multiple Nakama nodes behind a load balancer, as covered in the advanced tips section, is the standard path. Running your own load test, as described earlier in this guide, is the only reliable way to get a number specific to your game rather than relying on a generic rule of thumb.

Should I run Nakama in Kubernetes instead of Docker Compose?

Docker Compose is the fastest path to a working deployment and is fine for small-to-medium production workloads. Once you need autoscaling, rolling deploys, or you’re already running other game infrastructure on Kubernetes — such as an Agones-based dedicated server fleet — migrating Nakama to the same cluster keeps your operations tooling consistent.

Can I switch from self-hosted Nakama to Heroic Cloud later without rewriting my game?

Yes, since Heroic Cloud runs the same open-source Nakama server under the hood. Your client-side integration code and server runtime modules carry over; the migration is primarily a matter of exporting your database and pointing the client SDK at the new server address.

What’s the difference between the Nakama Console port and the client API port?

Port 7351 serves the Nakama Console, a web-based admin dashboard for managing players, viewing storage data, and configuring the server — it should never be exposed to the public internet. Port 7350 is the client-facing HTTP and WebSocket gateway that your actual game connects to, and it’s the port you put behind TLS in Step 12. Port 7349, the third default port, carries gRPC traffic for server-to-server calls and advanced client integrations that talk gRPC directly instead of going through the HTTP gateway — most teams using the standard client SDKs never need to touch it directly.

Does Nakama support cross-platform play between Unity, Unreal, and mobile clients?

Yes. Because every client SDK talks to the same HTTP, WebSocket, and gRPC APIs regardless of engine, a Unity PC client, an Unreal console build, and a mobile app built with the Java/Android or Swift SDK can all authenticate against the same Nakama server, join the same matches, and share the same leaderboards and social graph. Cross-platform play is a property of your game design and authentication strategy rather than something Nakama restricts at the server level.

Marcus Chen

Marcus Chen

Gaming & Consumer Tech Editor

Marcus Chen is a senior editor at Tech Insider, where he leads coverage of the US online gaming market, including sweepstakes and social casinos, alongside consumer technology. He evaluates operators on their published terms, licensing and RNG certifications, stated redemption policies, and corroborating independent reporting, and writes plainly about what the evidence supports. Tech Insider does not run first-party money tests and does not gamble with reader funds. Marcus has reported on the technology and online-gaming industries for more than a decade.

View all articles