Plugin Documentation

S3Vault
Cloud saves, player files and content on Amazon S3

Store save games, player files and downloadable content in Amazon S3 from Blueprints and C++. Files are streamed from and to disk with progress, every player gets their own folder, and credentials come from an Amazon Cognito identity pool.

v1.0
UE 4.27 & 5.8
Win64, Linux & Android
Category Networking
Alpha XP

Overview

S3Vault connects your game to Amazon S3 without a server of your own. Players sign in to (or get a guest identity from) an Amazon Cognito identity pool, receive temporary AWS credentials, and read and write objects in your bucket — limited by an IAM policy to their own folder.

  • Save Game To Cloud / Load Game From Cloud for any Save Game object.
  • Files are streamed from and to disk, never loaded whole into memory; large files are uploaded in parallel parts.
  • Downloads go to <file>.part and are renamed when complete, so a failed or cancelled download never leaves a broken file.
  • Folder downloads for content packs, with Skip Existing to fetch only what changed in size.
  • List, inspect, copy and delete objects; presigned GET and PUT links.
  • Every node is latent and cancellable; requests run on worker threads and results arrive on the game thread.

S3Vault has 28 Blueprint nodes: 17 latent nodes, 9 configuration and identity functions and the Cancel / Is Finished functions of every latent node.

Requirements

RequirementDetails
Unreal Engine4.27 and 5.8 (one source, verified clean on both)
ModulesS3Vault (Runtime), S3VaultSdk (External — the prebuilt AWS SDK for C++ 1.11.916)
DependenciesNone (engine modules only; no other plugins are enabled)
PlatformsWin64, Linux, Android. On Linux and Android the SDK uses the engine's libcurl, OpenSSL and certificate store.
AWSAn AWS account with an S3 bucket and (for players) a Cognito identity pool. S3 storage, requests, data transfer and Cognito usage are billed by AWS.

Installation

  1. Install S3Vault from Fab into your engine, or copy the S3Vault folder into your project's Plugins folder.
  2. Open the project, enable S3Vault in Edit > Plugins and restart the editor.
  3. Open Project Settings > Plugins > S3Vault and set Region, Identity Pool Id, Default Bucket and Key Prefix.
  4. C++ only: add PublicDependencyModuleNames.Add("S3Vault"); to your Build.cs.
Verifying the installCall Is Configured — it returns false with a reason until the settings are complete. Resolve Identity then proves that the identity pool hands out credentials.

Setting up AWS

  1. Bucket. In the S3 console create a bucket (for example my-game-saves) in the region you set in the project settings. Keep Block all public access enabled — players reach the bucket with their own credentials, not publicly.
  2. Identity pool. In Amazon Cognito create an identity pool. Enable guest (unauthenticated) access if players should save before signing in, and add the identity providers you use (a Cognito user pool, Google, Apple, Facebook or OpenID). Copy the pool id (us-east-1:0123...) to Identity Pool Id.
  3. Role policy. Attach the policy below to the pool's authenticated role (and to the guest role if you allow guests). Replace my-game-saves, and use the same folder as your Key Prefix (players/{IdentityId}).
  4. Optional: enable Transfer Acceleration on the bucket and tick Use Transfer Acceleration for faster uploads from far-away players.
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ListOwnFolderAndContent",
      "Effect": "Allow",
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::my-game-saves",
      "Condition": {
        "StringLike": {
          "s3:prefix": [
            "players/${cognito-identity.amazonaws.com:sub}/*",
            "dlc/*"
          ]
        }
      }
    },
    {
      "Sid": "ReadWriteOwnFiles",
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:DeleteObject",
        "s3:AbortMultipartUpload",
        "s3:ListMultipartUploadParts"
      ],
      "Resource": "arn:aws:s3:::my-game-saves/players/${cognito-identity.amazonaws.com:sub}/*"
    },
    {
      "Sid": "ReadSharedContent",
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-game-saves/dlc/*"
    }
  ]
}

${cognito-identity.amazonaws.com:sub} is the player's Cognito identity id — exactly what S3Vault puts in place of {IdentityId}, so every player can only list, read, write and delete below their own players/<identity id>/ folder. The dlc/ statements give every player read access to shared content (download it with an absolute key such as /dlc/pack1/); drop them if you do not ship content packs.

Never ship long-term keysStatic keys in the project settings end up in DefaultGame.ini and in every packaged build. They are refused in Shipping builds unless Allow Static Keys In Shipping is set — use that only for dedicated servers.
Signed-in players get a different identityA guest and the same player after Set Login Token are different identities unless your pool merges them, so their folders differ. Sign the player in before the first save, or copy the guest's files after login with Copy Object while both identities are known to your backend.

Keys & prefixes

Every node takes a Bucket (empty = Default Bucket) and a Key. Keys are relative to the Key Prefix unless they start with /:

Key PrefixKeyS3 key
players/{IdentityId}saves/slot1.savplayers/us-east-1:1a2b.../saves/slot1.sav
players/{IdentityId}/dlc/pack1/Pack1.pakdlc/pack1/Pack1.pak
{Region}/sharedmotd.jsonus-east-1/shared/motd.json
(empty)saves/slot1.savsaves/slot1.sav

Tokens: {IdentityId} = the player's Cognito identity id (resolved automatically before every request in Cognito Identity Pool mode; in the other modes a key that uses it fails with IdentityUnavailable), {Region} = the configured region. Resolve Key shows the final key. Keys returned by the nodes (Info > Key, list results, failed keys) use the same relative form, so you can pass them straight back; Info > Full Key holds the complete S3 key.

Prefixes work like folders: saves/ matches everything in the saves folder, saves also matches saves-old/.... The folder nodes always treat their prefix as a folder.

Local paths that are relative are relative to the project's Saved folder; absolute paths are used as given (for content packs, Project Persistent Download Dir is a good choice on every platform).

Quick start

Blueprint

  1. Create your Save Game object as usual (Create Save Game Object) and fill it.
  2. Add Save Game To Cloud, connect the object and set Key to saves/slot1.sav.
  3. To load, add Load Game From Cloud with the same Key and cast Save Game on On Success to your class.
  4. On On Failure, check Error > Code: NoSuchKey means there is no cloud save yet.
  5. For big files use Upload File / Download File and bind On Progress to a progress bar (Bytes Done / Total Bytes).

C++

// Build.cs: PublicDependencyModuleNames.Add("S3Vault");
#include "S3VaultAsyncActions.h"

void AMyGameMode::DownloadPack()
{
    US3VaultDownloadFolderAction* Action = US3VaultDownloadFolderAction::DownloadFolder(this,
        TEXT("/dlc/pack1/"), FPaths::ProjectPersistentDownloadDir() / TEXT("Pack1"), FString(), /*bSkipExisting*/ true);
    Action->OnProgress.AddDynamic(this, &AMyGameMode::OnPackProgress); // (int32 FilesDone, int32 FilesTotal)
    Action->OnSuccess.AddDynamic(this, &AMyGameMode::OnPackDone);      // (int32 FileCount, const TArray<FString>& FailedFiles, const FS3VaultError& Error)
    Action->OnFailure.AddDynamic(this, &AMyGameMode::OnPackDone);
    Action->Activate();
}

Every latent node is a UBlueprintAsyncActionBase: call its static factory, bind the delegates (they are dynamic, so the handlers must be UFUNCTIONs), then call Activate(). Keep the returned pointer if you want to call Cancel().

Uploads & downloads

NodeTypeDescription
Upload FileLatentPins: Local Path, Key, advanced Content Type (empty = from the extension), Metadata (user metadata, sent as x-amz-meta-*), Bucket. Streams the file; above Multipart Threshold MB it is uploaded in parallel 8 MB parts. On Progress (Bytes Done, Total Bytes), On Success / On Failure (Info, Error).
Upload BytesLatentPins: Data (byte array), Key, Content Type (empty = application/octet-stream), Metadata, Bucket.
Upload StringLatentPins: Text (sent as UTF-8), Key, Metadata, Bucket, Content Type (default text/plain; charset=utf-8; use application/json for JSON).
Download FileLatentPins: Key, Local Path, Bucket. Writes to <Local Path>.part, renames it when complete and creates missing folders. On Progress (Bytes Done, Total Bytes), On Success / On Failure (Info, Error).
Download BytesLatentPins: Key, Bucket. Returns Data, Info, Error. For objects that fit in memory.
Download StringLatentPins: Key, Bucket. Returns Text (UTF-8 decoded, byte order mark removed), Info, Error.

Progress is reported at most about 10 times per second, always on the game thread. Cancel stops the request immediately; a cancelled multipart upload is aborted on S3 so no orphaned parts are billed.

Save games

NodeTypeDescription
Save Game To CloudLatentPins: Save Game, Key, Bucket. Serializes the object with the engine's Save Game To Memory (the same format as Save Game To Slot) when the node is called, then uploads it.
Load Game From CloudLatentPins: Key, Bucket. Downloads and recreates the object with Load Game From Memory. On Success (Save Game, Info, Error), On Failure — InvalidSaveGame when the data is not a save game or its class no longer exists.
Conflicts between devicesStore a timestamp or play time in your Save Game, or compare Info > Last Modified from Get Object Info with the local slot before deciding which save wins. Copy Object keeps a backup (for example saves/slot1.bak) before you overwrite a save.

Folders & content packs

NodeTypeDescription
Download FolderLatentPins: Prefix, Local Directory, Bucket, advanced Skip Existing. Lists every object below the prefix and downloads them one by one, keeping sub folders. Skip Existing keeps local files whose size matches. Keys that are not safe relative paths (.., drive letters) are skipped and reported. On Progress (Files Done, Files Total), On Success / On Failure (File Count, Failed Files, Error).
Upload FolderLatentPins: Local Directory, Prefix, Bucket. Uploads every file (recursively, .part files excluded) with content types from the extensions; large files use multipart uploads. Same output pins as Download Folder.

A failed file does not stop the others: the node finishes with On Failure, the number of files that succeeded and the list of failed files, and Error describes the first failure.

Object management

NodeTypeDescription
List ObjectsLatentPins: Prefix, Continuation Token, Bucket, advanced Delimiter (default /) and Max Keys (1–1000). Result holds Objects, Common Prefixes (sub folders when a delimiter is set), Next Token and Truncated. Pass Next Token back as Continuation Token for the next page.
Get Object InfoLatentPins: Key, Bucket. Size, last modified, ETag, storage class, content type and metadata without downloading. On Not Found fires when the key does not exist. With the per-player policy S3 answers 403 instead of 404 for missing keys; S3Vault then checks with a one-key list request and still reports Not Found (downloads report NoSuchKey the same way), so keep the s3:ListBucket statement in the policy.
Copy ObjectLatentPins: Source Key, Dest Key, advanced Source Bucket (empty = the destination bucket) and Bucket. Server-side copy up to 5 GB; content type and metadata are kept.
Delete ObjectLatentPins: Key, Bucket. Deleting a key that does not exist also succeeds.
Delete ObjectsLatentPins: Keys, Prefix, Bucket. Deletes every key in Keys, or — when Keys is empty — every object below Prefix, in requests of 1000 keys. Returns Deleted Count and Failed Keys. With no Key Prefix and an empty Prefix the node refuses to run; pass Prefix / to empty the whole bucket on purpose.
Get Presigned URLLatentPins: Key, Bucket, Verb (GET or PUT), Expires Seconds (default 3600, at most 7 days). Returns a URL anyone can use without credentials until it expires. A PUT URL uploads the request body as the object. With Cognito credentials the URL also stops working when the temporary credentials expire (at most one hour).

Identity & configuration

NodeTypeDescription
Resolve IdentityLatentPin: Force Refresh. Fetches the Cognito identity and temporary credentials now (every request also does this on demand) and returns the Identity Id.
Set Login TokenCallableSigns the player in to the identity pool: Provider is the pool's login key (for example accounts.google.com, appleid.apple.com, or see Make User Pool Provider Name), Token the provider's ID token. The cached identity is replaced.
Clear Login TokensCallableForgets all tokens and the identity; the player is a guest again.
Set Static CredentialsCallableUses the given keys (and optional session token) from now on and switches to Static Keys mode — for example temporary keys handed out by your own backend.
Set RegionCallableOverrides the region for every following request.
Set Credential ModeCallableOverrides the credential mode at runtime.
Get Identity IdPureThe player's Cognito identity id; empty until credentials were resolved once.
Make User Pool Provider NamePureBuilds cognito-idp.<region>.amazonaws.com/<user pool id> (the region is taken from the pool id when empty).
Is ConfiguredPureFalse with a Problem text when the settings are incomplete.
Resolve KeyPureThe S3 key a node would use for a Key (prefix and tokens applied). {IdentityId} stays as written until the identity was resolved.
CancelCallableOn any latent node: stops the request or transfer; none of its pins fire afterwards.
Is FinishedPureOn any latent node: true after it completed or was cancelled.

Types

TypeKindDescription
FS3VaultObjectInfoStructKey (relative form), Full Key, Size (int64 bytes), Last Modified (UTC), ETag, Storage Class, Content Type and Metadata (filled by uploads, downloads and Get Object Info).
FS3VaultListResultStructObjects, Common Prefixes, Next Token, Truncated.
FS3VaultErrorStructCode, Message, Http Status (0 when AWS was not reached), Retryable.
ES3VaultCredentialModeEnumCognito Identity Pool, Static Keys, Default Credential Chain.
ES3VaultUrlVerbEnumGET, PUT.

Settings

Project Settings > Plugins > S3Vault (saved to DefaultGame.ini). Changes apply to the next request.

SettingDefaultDescription
Regionus-east-1Region of the bucket and the identity pool. The bucket must be in this region.
Credential ModeCognito Identity PoolWhere request credentials come from.
Identity Pool Id—The Cognito identity pool.
Allow Guest AccesstrueUse guest identities before Set Login Token (the pool must allow them too).
Access Key Id / Secret Access Key—Static Keys mode (development and servers).
Allow Static Keys In ShippingfalseAdvanced. Static keys from the settings are refused in Shipping builds unless enabled.
Default Bucket—Bucket used when a node leaves Bucket empty.
Key Prefix—Folder for relative keys, with the {IdentityId} and {Region} tokens, for example players/{IdentityId}.
Multipart Threshold MB16Files larger than this are uploaded in parallel 8 MB parts (5–4096). The transfer buffers (32 MB) are allocated on the first multipart upload.
Use Transfer AccelerationfalseUse S3 Transfer Acceleration endpoints. Must be enabled on the bucket; ignored with an Endpoint Override.
Endpoint Override—Advanced. A local S3-compatible emulator such as http://localhost:4566 (path-style addressing).
Request Timeout Ms30000Longest time a request may go without receiving data.
Connect Timeout Ms5000Time allowed to open a connection.
Max Retries3Automatic retries with back-off for throttling and transient errors.
Worker Threads4Advanced. Requests that run at the same time.
Verify SSLtrueAdvanced. Only disable for a local emulator.
Log Sdk WarningstrueAdvanced. SDK warnings and errors go to the Output Log (LogS3Vault).

Error codes

CodeMeaning
NoSuchKeyThe object does not exist (downloads).
NotFoundGet Object Info: the object does not exist (On Not Found).
AccessDeniedThe IAM policy does not allow this key or action — check the Key Prefix against the policy.
NoSuchBucket / PermanentRedirectWrong bucket name, or the bucket is in another region than the settings.
NotConfigured / NotSignedInSettings incomplete, or guest access disabled before Set Login Token.
IdentityUnavailableThe key uses {IdentityId} but there is no Cognito identity (Static Keys or Default Chain mode).
InvalidKey / InvalidPrefix / InvalidPathEmpty key, key ending in /, unsafe bulk delete, or no local path.
FileNotFound / FileOpenFailed / WriteFailed / DirectoryNotFoundLocal file system problems.
InvalidSaveGame / TooLargeSave game could not be (de)serialized; object too large for Download Bytes.
Cancelled / Unavailable / ShuttingDown / NetworkErrorCancelled by you, SDK library missing or module shutting down, or no connection (Retryable = true).

Troubleshooting

SymptomCause and fix
AccessDenied for every keyThe Key Prefix does not match the policy. Use players/{IdentityId} with the policy above, and attach the policy to the role the player actually gets (guest or authenticated).
Saves "disappear" after sign-inThe signed-in player has a new identity id and therefore a new folder. See Signed-in players get a different identity above.
PermanentRedirectThe bucket is in another region. Set Region to the bucket's region (or call Set Region).
Uploads larger than the threshold fail with AccessDeniedMultipart uploads need s3:PutObject and, for clean-up, s3:AbortMultipartUpload on the same keys.
A presigned URL returns 403 after a whileIt was signed with temporary Cognito credentials, which expire within an hour regardless of Expires Seconds.
A .part file is left next to a downloadThe game was closed during the download. It is overwritten by the next download and never uploaded by Upload Folder.
Requests fail with Unavailable on WindowsS3VaultSdk.dll could not be loaded — the Output Log has the path. Reinstall the plugin so Source/ThirdParty/S3VaultSdk/Win64 is complete.

Credits

© 2026 Alpha XP — alphaxp.net · Support: support@alphaxp.net. Built and verified for Unreal Engine 4.27 and 5.8. Includes the AWS SDK for C++ 1.11.916 (Apache-2.0).