Save Data

Overview

Save Data stores data in persistent storage for later retrieval within flows or across different flow executions. Use this stage to persist user sessions, maintain state, store temporary or long-term values, or share data between flows.

* Example flow demonstrating how Save Data stores a player's campaign participation details after a successful qualifying deposit and makes the saved values immediately available for use in later stages.

Note: The variable names, values, criteria, and configuration used in this example are for demonstration purposes only.

Where to find it: Actions > Local Storage in the stage library.

Configuration

Required Fields

FieldDescriptionExample
Group nameThe organizational namespace for your data (groups related data together)userSessions, orderCache
Key (Name)The identifier for the stored valueuserId, lastOrderDate
ValueThe data to store (static value, variable, or formula starting with =){{userEmail}}, John, ={{price}}*1.1

Also Required

  • Record name: Required. A sub-grouping within the group name for hierarchical organization (e.g., individual user records within a users group). The builder now marks this as required, and a save with no Record name is rejected.
  • Time to live (minutes): Required. How long to keep the data before automatic deletion. Use @forever for permanent storage, @1_hour (60 min), @24_hours (1440 min), or a specific number of minutes. A save with no TTL is rejected.

Using functions in these fields: Any value field above accepts @ functions, for example @NowSecond for the current time or @calc(...) for a calculation. 

See Flows Functions for the full list.

Exit Points

ExitWhen
PassData successfully saved to storage
ErrorOnly for a failure before the save runs (e.g. a variable that can't resolve). A database error does NOT reach this exit

Important: a database/storage error during the save does not route to the Error exit. It is handled internally and the stage still takes Pass, with the error logged. To confirm a save actually landed, follow with a Fetch Data stage and check the value.

How It Works

When executed, the stage:

  1. Resolves configuration - Evaluates group name, record name, TTL, and all key-value pairs
  2. Saves each key-value pair - Stores data to persistent storage (one key at a time)
  3. Updates flow variables - Adds saved values to flow dictionary for immediate use
  4. Clears cache (if specified) - Optionally clears distributed cache across servers

Time to Live (TTL) Options

ValueDurationUse Case
@forever or 0Permanent (no expiration)Configuration settings, permanent counters
@1_hour60 minutesShort-term caching, rate limiting
@24_hours1440 minutes (24 hours)Daily data, user sessions
Numeric value (e.g., 30)Specified minutesCustom expiration timing

Common Use Cases

1. Store User Session

Save user login information for session management.

  • Group name: userSessions
  • Record name: {{userId}}
  • Time to live: @24_hours
  • Keys:
    • loginTime → {{currentTimestamp}}
    • ipAddress → {{requestIp}}
    • userEmail → {{email}}

2. Cache API Response

Store API response to avoid repeated external calls.

  • Group name: apiCache
  • Record name: productData
  • Time to live: 60 (1 hour)
  • Keys:
    • products → {{apiResponse.data}}
    • fetchedAt → {{currentTime}}

3. Store Form Submission

Save multi-step form data as user progresses.

  • Group name: formSubmissions
  • Record name: {{sessionId}}
  • Time to live: @forever
  • Keys:
    • step1_personalInfo → {{formData1}}
    • step2_address → {{formData2}}
    • status → in_progress

4. Track Rate Limiting

Store request counts for rate limit enforcement.

  • Group name: rateLimits
  • Record name: {{userId}}
  • Time to live: 60 (reset hourly)
  • Keys:
    • requestCount → 1
    • firstRequest → {{timestamp}}

Key Behaviors

FeatureBehavior
OverwriteSaving to existing group+record+key overwrites the previous value completely
Multiple Keys✓ Save multiple key-value pairs in one stage
Dictionary Update✓ Saved values immediately available as flow variables
TTL Reset✓ Each save resets the expiration timer to the new TTL
Non-AtomicKeys saved one at a time (no transaction across multiple keys)
Cache Clear✓ Prefix group name with cache:: to clear distributed cache

Accessing Saved Data

After the stage executes, each saved key is automatically added to your flow variables:

Example:

  • Save key userEmail with value [email protected]
  • Use it immediately as {{userEmail}} in subsequent stages
  • To retrieve later (in another flow execution), use Fetch Data stage

Save Data vs Increment Number

Use CaseSave DataIncrement Number
Concurrent updates to counters✗ Race conditions - lost updates✓ Atomic - safe for concurrent access
Storing text/objects/arrays✓ Any data type✗ Numbers only
Single flow updating value✓ Simple and sufficient✓ Works but overkill
Running counters✗ Use Increment Number instead✓ Designed for this

Key rule: For numeric counters updated by multiple concurrent flows, use Increment Number. For all other data, use Save Data.

Best Practices

  • ✓ Use descriptive group and key names like userSessions.loginTime
  • ✓ Set appropriate TTLs - use @forever for permanent data, time-based for temporary
  • ✓ Use Increment Number instead of Save Data for concurrent counter updates
  • ✓ Save multiple related keys together in one stage (more efficient)
  • ✓ Use record names for entity-based organization (e.g., per-user data)
  • ✓ Connect Error exit to handle database connection failures
  • ✓ Document your data schema (which groups, records, and keys are used where)
  • ✓ Use cache:: prefix when saving frequently accessed data that might be cached

Common Mistakes

MistakeSymptomFix
Using Save Data for concurrent countersCounter values inconsistent, some updates lostUse Increment Number for counters updated by multiple flows simultaneously
Forgetting TTL for temporary dataData persists indefinitely, bloats storageSet appropriate TTL for sessions, caches, temporary tracking data
Using inconsistent namesCan't retrieve data - fetch returns defaultsUse exact same group/record/key names in Fetch Data as in Save Data
Not handling Error exitFlow fails silently when database unavailableConnect Error exit to retry logic or alerting
Expecting transactional savesPartial data saved when error occurs mid-wayKeys saved one at a time; implement custom transaction logic if needed
Overwriting data unintentionallyPrevious value lostRemember that saving to existing key overwrites completely (no merging)

Troubleshooting

IssueExit/ResultCommon CauseFix
Data not persistingPass (but data doesn't save)Very short TTL or data overwritten by another flowCheck TTL value; verify no other flows using same group+record+key
Save failed but flow continued anywayPass (error swallowed)A database/storage error is handled internally, so the stage passes instead of taking the Error exitCheck logs for the storage error; use Fetch Data after Save to confirm the value landed
Can't retrieve saved dataN/A (affects Fetch Data)Name mismatch or data expiredVerify exact group/record/key names match; check TTL hasn't expired
Counters inconsistentPass (but wrong values)Using Save Data for concurrent counter updatesSwitch to Increment Number for atomic counter operations
Partial data savedError (after some keys saved)Error occurred mid-way through saving multiple keysKeys saved before error remain in storage; check which keys succeeded

Cache Clearing

Prefix the group name with cache:: to clear distributed cache when saving:

Example: cache::userSessions

This will:

  • Save the data to storage
  • Send message to all servers to clear their cached copies
  • Remove value from local memory cache
  • Ensure fresh data is loaded on next read

Related Stages

  • Fetch Data: Retrieve data that was saved by this stage
  • Delete Data: Remove saved data when it is no longer needed
  • Increment Number: Safely update numeric counters; use this instead of Save Data for concurrent counters
  • Query Data: Search saved data based on configured conditions
  • Change Data: Set variables before saving them