How to use Satori for Effective Session Management

This guide explains how to effectively use Satori for session management, covering the different approaches to starting sessions and sending events, key differences between client-side and server-side events, and best practices.

The following sections describe different scenarios depending on your project setup. Consult the scenario that applies to your specific use case.

Prerequisites #

Before you begin, ensure you have:

  • An understanding of how Sessions behave in Satori

Player-Driven Sessions (Client-Side) #

This scenario applies to your project if you are using:

  • Satori only
  • A Nakama client (with or without websockets) and Satori

This setup reduces server-side complexity and scales well across global clients. Clients emit real-time game telemtry and analytics directly to Satori, resulting in a simple, low-latency solution. When integrated with Nakama, this setup ensures a unified player identity across both services.

Creating Sessions #

Sessions should be created client-side using Satori’s built-in authentication. When a user is authenticated through Satori, it automatically creates a session for the user. This should be done when the player opens the game or logs in.

Example using the Unity SDK:

1
2
3
4
5
6
7
8
9
const string scheme = "http";
const string host = "127.0.0.1";
const int port = 7450;
const string apiKey = "apiKey";

// Ensure you are using Client from the Satori namespace
var client = new Client(scheme, host, port, apiKey);

var session = await client.AuthenticateAsync("<user_id>");

Sending Events #

Events should be sent directly from the client to Satori using the event() method.

Example using the Unity SDK:

1
await client.EventAsync(session, new Event("gameFinished", DateTime.UtcNow));

Game-Authoritative Sessions (Server-Side) #

This scenario applies to your project if you are using:

  • Nakama server

This setup ensures data integrity for critical game mechanics by processing events through authoritative server logic. As a result, Satori receives validated, authoritative events from your Nakama server, complementing client-side data.

Creating Sessions #

For events originating from the Nakama server (e.g., server-authoritative game logic), Satori sessions are typically created within Nakama’s server-side modules or webhooks.

Example using Nakama in Go:

1
2
3
satori := nk.GetSatori()
userId := "user-id"
satori.Authenticate(ctx, userId)

Sending Events #

Events that require server-authoritative validation, complex logic, or are generated by Nakama itself (e.g., match results, economy updates, background events) should be sent from Nakama’s server-side code (modules or webhooks) to Satori.

Example using Nakama in Go:

1
2
3
4
5
6
7
8
9
satori.EventsPublish(ctx, "identityId", []*runtime.Event{{
  Name: "eventName",
  Id: "optionalEventId",
  Metadata: map[string]string{
    "someKey": "someValue",
  },
  Value: "someValue",
  Timestamp: time.Now().Unix(),
}})

Background Events and System Sessions #

The following steps describe your setup if you have or are using:

  • Third party servers
  • Background events (e.g., headless servers)
  • Non-player events (e.g., from the system, cron jobs, or other metrics)

With this setup, Satori has a comprehensive view of the game’s operations, including player events processed through Nakama (if applicable), and critical background events from your server infrastructure. It maintains a clear distinction between player and system events while allowing for independent data submission from backend systems. This also allows for advanced analytics around overall game health and the impact of server-side changes on player engagement.

Creating Sessions #

For events that are not tied to a specific player’s active session (e.g., server-generated events, headless server actions, third-party system updates), create Satori sessions directly from your backend services (e.g., dedicated game servers, cron jobs, external analytics platforms). These sessions might be “system” sessions or associated with specific non-player entities.

To authenticate your backend service with Satori, you can use the /v1/console/authenticate endpoint with your console credentials (email and password) to obtain an authentication token. This token can then be used to establish a session for sending events.

Example using the /v1/console/authenticate API Endpoint:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
async function authenticateSatoriConsole(email, password) {
  const response = await fetch(
    "http://your-satori-host:7450/v1/console/authenticate",
    {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ email, password }),
    }
  );
  const data = await response.json();
  return data.token; // Returns the authentication token
}

Sending Events #

Events from headless servers, background processes, or other third-party services should be sent directly from those servers to Satori using the POST /v1/server-event endpoint. These events might represent server-side simulations, bot activities, or external data integrations.

Example using the /v1/server-event API Endpoint:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
async function sendServerEvent(token, eventData) {
  const response = await fetch("http://your-satori-host:7450/v1/server-event", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${token}`, // Use the obtained token for authorization
    },
    body: JSON.stringify({ events: [eventData] }),
  });
  if (!response.ok) {
    const error = await response.json();
    console.error("Failed to send server event:", error);
  } else {
    console.log("Server event sent successfully!");
  }
}

Read more about sending server-side events in the Server Events API guide.

Conclusion #

Effective session management with Satori is crucial for gaining deep insights into player behavior and optimizing your live operations. By carefully considering where and how sessions are created and events are sent, you can ensure data consistency, minimize latency, and build a robust analytics pipeline that supports your game’s growth and player engagement strategies.