Migrating from PlayFab to Crux: A 10-Step Checklist (2026)

A 10-step PlayFab to Crux migration: export player data, map APIs, handle cloud functions, move billing, and cut over without downtime.

Microsoft PlayFab is a mature live-ops backend, but indie and mid-size studios increasingly hit the same set of friction points: confusing usage-based pricing that's hard to forecast, mandatory Azure account dependencies, an enormous API surface that punishes simple games, and rising concern about long-term Microsoft commitment to PlayFab as a standalone product (GameSparks was sunset in 2024). This guide walks through migrating a live game's backend from PlayFab to Crux with zero downtime.

Migration takes 1-3 weeks for a typical indie game, depending on how deep you've gone into PlayFab Cloud Script and Azure Functions. The data export itself is fast; rewriting integrations is the real work.

Before You Start: Is Crux the Right Replacement?

Crux replaces PlayFab cleanly if your game uses PlayFab primarily for: player auth, save sync (player-scoped JSON documents), leaderboards, friends, matchmaking, virtual currencies, inventory, and dedicated-server registry. Crux does not currently replace PlayFab if you depend heavily on Azure-specific features like Application Insights, Azure A/B testing, or PlayFab Multiplayer Servers (the orchestration layer - Supercraft hosting is the equivalent but you'd treat it as a separate product).

Read the PlayFab vs Crux comparison first if you're still in the decision phase.

If PlayFab's current Development Mode limit, Foundation Mode eligibility, or metered paid plans pushed you to migrate, that breakdown explains which path applies to your title.

Shortcut: the compatibility layer

The rewrite is usually not the backend, it is the call sites. crux-playfab-compat keeps them: it accepts PlayFab's request shapes, returns PlayFab's { code, status, data } envelope, and supports both the callback and the promise/Task style, so the diff is which client you construct.

npm install crux-playfab-compat

const PlayFabClientAPI = new PlayFabClientCompat(
  CruxClient.forPlayer(baseUrl, projectId, environmentId, apiKey),
);

// unchanged from your PlayFab codebase
PlayFabClientAPI.GetUserData({ Keys: ["save"] }, (res, err) => { /* ... */ });

It ships for JavaScript/TypeScript, for Unity (C#) and for Godot (GDScript) - between them, where most PlayFab titles actually live. The Unity and Godot versions come inside those SDK packages; the JavaScript one is on npm. It covers what an ordinary title calls every session: the Login* methods, GetUserData/UpdateUserData, GetTitleData, GetLeaderboard, GetLeaderboardAroundPlayer, UpdatePlayerStatistics, GetUserInventory, AddUserVirtualCurrency, SubtractUserVirtualCurrency and the friends calls.

Everything outside that set fails explicitly rather than quietly doing nothing. JavaScript and C# throw an unsupported-method error; GDScript returns a non-success error envelope. That is deliberate: a stub that silently succeeds looks like it worked, and for a currency or receipt call, "looks like it worked" is somebody's money. Methods with no Crux equivalent - characters, receipt validation, shared groups, trading, segments, push, CDN content, Photon tokens - tell you what is missing and what to do instead.

Three behaviours differ on purpose, and the layer does not paper over them:

  • AddFriend returns Created: false. PlayFab friends immediately; Crux sends a request the other player accepts. Reporting true would be a lie your UI would act on.
  • Leaderboard Position stays 0-based to match PlayFab, converted from Crux's 1-based ranks.
  • GetUserData/UpdateUserData share one Crux document, so multi-key writes stay atomic. Updates merge, null deletes, and the read version is passed back for optimistic concurrency.

ExecuteCloudScript is not supported, and that is the one gap worth planning around before you start - see the step below.

The 10-Step Checklist

Step 1: Audit your PlayFab usage

List every PlayFab API call your client and server code makes today. Group them by category: auth, player data, leaderboards, virtual currency, inventory, cloud script / Azure Functions, multiplayer matchmaking, analytics events. This list becomes your migration spec.

Pull a 30-day call-volume report from the PlayFab dashboard. Anything called <1% of total volume can usually be deferred or dropped during migration.

Step 2: Map PlayFab APIs to Crux equivalents

PlayFab Crux equivalent Notes
LoginWithEmailAddress / LoginWithCustomID POST /v1/auth/login (email + password) / POST /v1/auth/anonymous Direct mapping. Crux also supports OAuth (Google, Apple, Steam).
UpdateUserData / GetUserData Player JSON docs with patch semantics Crux uses RFC 6902 JSON patch. Map PlayFab key/value pairs into a single document.
UpdatePlayerStatistics / GetLeaderboard Leaderboards API Direct mapping. Seasonal boards supported.
AddUserVirtualCurrency / SubtractUserVirtualCurrency Currencies API with atomic transactions Direct mapping; atomic semantics for multi-currency operations.
GrantItemToUser / GetUserInventory Inventory API Direct mapping. Stack-based and unique-item modes both supported.
PlayFab Cloud Script (JavaScript) / Azure Functions Your own service, called by Crux webhooks Crux does not execute your code, but it does call yours: subscribe to events and Crux POSTs a signed payload when they fire. If your CloudScript already runs on Azure Functions, keep it and change only what invokes it. Still the largest item in the migration.
Matchmaking API Crux matchmaker Map your queue config; rule-set semantics differ slightly.
GetTitleData (live config) Live config bundles, environment-based Crux ships environment-aware bundles; map your title-data keys to bundle versions.

Step 3: Export your PlayFab player data

Use PlayFab's GetPlayerSegmentReport or the data export feature in the PlayFab dashboard to dump all player accounts, statistics, virtual currency, and inventory state. The export typically produces JSON or CSV chunks.

Critical: capture player IDs alongside the data. You'll need to map PlayFab IDs to Crux IDs in step 7.

Step 4: Set up your Crux project

Create a Crux project at crux.supercraft.host/pricing (start on free tier for migration testing). Configure your environments - typically dev, staging, prod. Generate API keys for each.

Step 5: Build the import script

Write a one-shot import script that iterates your PlayFab export and creates equivalent Crux entities:

  • For each PlayFab player: create a Crux player with anonymous-promote auth, then merge in their email if present
  • For each statistic: write to the matching Crux leaderboard
  • For each virtual currency: write to the matching Crux currency
  • For each inventory item: write to Crux inventory
  • Write a mapping table: playfab_id -> crux_id

Test on staging first. Run import in batches of 1,000 players to monitor for errors.

Step 6: Rehome your Cloud Script logic

This is the longest single step, and the one to be clear-eyed about: Crux does not execute your code. There is no Crux equivalent to drop CloudScript into. The logic moves to a service you run. For each function:

  • Identify the trigger (player call, scheduled task, server-side validation)
  • If it already runs on Azure Functions, keep it. Only the invocation path changes - your client calls your function directly instead of going through PlayFab
  • If it is PlayFab-hosted JavaScript, it needs a home: your game server, an existing backend service, or a small function on any provider
  • Have it talk to Crux with a server token. Anything that grants currency or validates a purchase must never be reachable with a client key
  • Write tests; the production data is the only audit you'll get

Crux calls you back. Rehoming the logic does not mean losing the trigger. Register an HTTPS endpoint against events like achievement.unlocked or stat.updated, and Crux POSTs a signed payload to your service when they happen - so "when they hit 100 kills, grant the reward" still fires from the backend, it just runs in your process instead of PlayFab's. Each delivery carries an HMAC-SHA256 signature and a timestamp inside the signed material, so you can verify it came from us and that it is not a replay.

Step 7: Update your client SDK calls

Replace PlayFab SDK calls in your game client with Crux SDK calls. Wrap each in a feature flag so you can toggle between PlayFab and Crux during the cutover.

Use the playfab_id -> crux_id mapping from step 5 so existing players see their progression seamlessly after the switch.

Step 8: Stage a parallel-write period

For 1-2 weeks before cutover, run both backends in parallel. Every player action writes to both PlayFab (current source of truth) and Crux (shadow). This catches mapping bugs before they hit production.

Compare data integrity daily. If Crux diverges from PlayFab by more than 0.1%, fix the import script and re-run.

Step 9: Cutover

Pick a low-traffic window (usually a weekday off-hour for your game's primary audience). Flip the feature flag from PlayFab to Crux. Monitor for 4 hours minimum.

Keep PlayFab in read-only mode for 30 days as a rollback safety net. Most migrations don't need to roll back, but the 30-day buffer covers edge cases.

Step 10: Decommission PlayFab

After 30 days of stable Crux-only operation:

  • Cancel your PlayFab subscription / Azure billing
  • Delete API keys
  • Archive the import scripts and mapping tables (don't delete - they're audit trail)
  • Remove PlayFab SDKs from your client codebase in the next release

Common Pitfalls

  • Cloud Script can dominate the migration. Inventory every server-side handler and dependency before estimating the schedule; data export is often easier than behavior parity.
  • PlayFab "PlayerData" keys are flat; Crux documents are nested JSON. Decide on a schema before you import - fixing it after is painful.
  • PlayFab analytics events do NOT migrate. If you depend on PlayFab's event tracking, plan a separate analytics solution (PostHog, Mixpanel, GameAnalytics). Crux does not ingest gameplay events.
  • Don't skip the parallel-write period. Cutting over without it is the #1 source of post-migration data loss.

Cost Comparison After Migration

Do not estimate savings from MAU alone. PlayFab meters specific services and Crux uses plan limits, so the answer depends on your actual call mix, storage, egress and any services that remain outside either backend. Pull a recent PlayFab usage report and put those numbers into the Crux cost calculator; keep the report beside the estimate so the comparison is auditable.

Bottom Line

A PlayFab migration can be small when you use a narrow subset of the API and much larger when CloudScript, Economy, multiplayer or custom Azure integrations are embedded in game logic. Estimate from the endpoint inventory and shadow-write results above, not from a generic “weeks” number. The payoff, if the fit is right, is a smaller API surface and a billing model you can compare directly against your measured usage.