Unreal Engine Dedicated Server Backend: SDK, REST & Persistence

Build a UE dedicated-server backend with Crux's beta C++ plugin or REST/OpenAPI fallback while Unreal keeps simulation authority and replication.

Unreal Engine already gives you the hard realtime part: an authoritative client/server model, replication, RPCs and a headless dedicated-server build. The production backend is a separate concern: identity, persistent player data, progression, leaderboards, live config and the registry/orchestration metadata that survives one server process.

Important boundary: Crux now ships a beta Unreal C++ plugin under sdks/sdk-unreal. Its wire protocol and structure tests pass, but it has not yet been compiled with Unreal Build Tool against the engine. Treat the first real UBT build/live call as part of evaluation. The public REST/OpenAPI surface through FHttpModule remains the verified fallback. Crux still does not host general Unreal dedicated-server fleets.

1. What Unreal already owns

Epic's current dedicated-server documentation describes Unreal's network multiplayer as authoritative client/server. A dedicated server is a headless game instance: no local player and no rendering, with remote clients connecting to the authoritative host. Epic notes listen servers can be reasonable for casual/co-op games, while dedicated servers are particularly useful for large-scale or competitive games.

The same Epic guide currently requires a source build and a C++ multiplayer project for its dedicated-server tutorial, and uses a separate Server.Target.cs target to build the server executable.

2. What the external backend owns

  • Identity: turn a guest/email/platform identity into a backend player session.
  • Persistence: saves, progression, inventory and other data that outlives the Unreal process.
  • Stats / achievements / leaderboards: backend-owned results rather than trusting the client that benefits from them.
  • Live config: operational values that should not require a new packaged build.
  • Server registry: advertise only healthy/joinable dedicated processes and expire stale ones.

3. Choose the beta plugin or Unreal's built-in HTTP module

The first-party plugin wraps the same public API used by every other Crux SDK. Copy sdks/sdk-unreal/Crux/ into your project's Plugins/ directory and add Crux to your target dependencies. Because the plugin has not yet had a real UBT build in this repository, keep the REST path available while you validate it.

#include "CruxClient.h"

TSharedPtr<FCruxClient> Crux = FCruxClient::ForPlayer(
    TEXT("https://crux.supercraft.host"),
    TEXT("YOUR_PROJECT_ID"),
    TEXT("YOUR_ENVIRONMENT_ID"),
    TEXT("YOUR_PUBLISHABLE_KEY")
);

Crux->LoginAnonymous(FString(), [Crux](const FCruxResult& Result)
{
    if (Result.bSuccess)
    {
        UE_LOG(LogTemp, Log, TEXT("player %s"), *Crux->GetPlayerId());
    }
});

If you prefer the lowest-level proof, or hit an engine-version issue in the beta plugin, Epic exposes FHttpModule and IHttpRequest for ordinary HTTP calls. The same anonymous-login request proves the wire contract without the plugin:

#include "HttpModule.h"
#include "Interfaces/IHttpRequest.h"

void UMyBackendService::BeginAnonymousLogin()
{
    TSharedRef<IHttpRequest, ESPMode::ThreadSafe> Request =
        FHttpModule::Get().CreateRequest();

    Request->SetURL(TEXT("https://crux.supercraft.host/v1/auth/anonymous"));
    Request->SetVerb(TEXT("POST"));
    Request->SetHeader(TEXT("Authorization"), TEXT("ApiKey YOUR_PUBLISHABLE_KEY"));
    Request->SetHeader(TEXT("Content-Type"), TEXT("application/json"));
    Request->SetContentAsString(TEXT("{}"));
    Request->OnProcessRequestComplete().BindUObject(
        this, &UMyBackendService::OnAnonymousLogin
    );
    Request->ProcessRequest();
}

The response gives you the player/session data needed for player-scoped calls. Persist the anonymous device id returned by the service so a guest does not become a fresh player on every launch.

4. Client and dedicated-server credentials are different

CallerCredentialRule
Shipped Unreal clientPublishable key + player tokenNever embed server/secret credentials
Trusted UE dedicated serverServer tokenAuthoritative cross-player and server-registry operations
Operator / CISecret operator credentialAdministrative operations only

5. Online Subsystem / Online Services are not the persistence layer by definition

Unreal provides Online Subsystem and the newer Online Services framework to integrate platform/online functionality such as Epic, Steam and console services. Keep those when they solve the platform job. A custom application backend is complementary when you need durable game-specific data or business rules behind your own HTTP contract.

6. Hosting and persistence must stay separable

Run the dedicated server with the hosting/orchestration provider that fits your fleet. Crux is not currently a UE process host. Your headless server can still register itself, heartbeat, read live config and write authoritative results through a stable backend API. That separation makes a future hosting migration a fleet change rather than a player-data migration.

7. Avoid these production mistakes

  • Inventing a validation endpoint. Use the actual OpenAPI contract rather than copying a blog URL that is not a deployed route.
  • Client-authoritative progression. Rewards with economic value should be validated or written by a trusted server/backend path.
  • Putting server tokens in packaged clients. Treat them as infrastructure secrets.
  • Assuming every UE game requires dedicated hosting. Choose listen vs dedicated based on authority, fairness, scale and product requirements.
  • Coupling fleet provider callbacks directly to player persistence. Keep provider-specific lifecycle code behind a thin adapter.

Primary references

Sources

Technical, pricing, and product claims were checked against these primary sources on the verification date above.