Skip to content

API Reference

Root Module

luau
local lsd = require("./lsd")

lsd.store(config)

Creates and returns a new Store instance.

luau
local store = lsd.store({
  name = "player_data",
  template = { ... },
})
  • Parameters: config: StoreConfig<T>
  • Returns: Store<T>

lsd.shutdown()

Closes all active stores and flushes pending data and telemetry. This is registered automatically with game:BindToClose.

luau
lsd.shutdown()

lsd.telemetry(callback)

Registers a telemetry sink callback that receives batched metrics and event logs every 10 seconds and on shutdown.

luau
local disconnect = lsd.telemetry(function(batch) ... end)
  • Parameters: callback: (batch: TelemetryBatch) -> ()
  • Returns: disconnect: () -> ()

lsd.validator

Namespace containing the schema definition and validation engine. See Validator API.


Store Configuration

Passed to lsd.store(config):

FieldTypeDefaultDescription
namestringRequiredDataStore namespace for player profiles.
templateTRequiredDefault data structure for new players and missing keys.
validate(data: T) -> booleannilValidator function or compiled schema.
migrations{ Migration<T> }{}Ordered list of versioned schema upgrades.
on_load_error(player, reason, message) -> ()nilHandler called when profile loading fails after all retries.
on_global_update(player, update, data) -> TnilHandler for queued cross-server global updates.
steal_on_lockedbooleanfalseAutomatically steal session lock if held by another server.
max_load_attemptsnumber3Maximum number of attempts before triggering on_load_error.

Store Instance

luau
local store = lsd.store(...)

store.load(player)

Yields while acquiring exclusive session ownership and loading the player's profile.

luau
store.load(player)

store.steal(player)

Immediately steals session ownership from any remote server and loads the player's profile.

luau
store.steal(player)

store.unload(player)

Closes the player's session, clears processed updates, saves pending changes, and releases ownership.

luau
store.unload(player)

store.get(player)

Returns the player's current profile. The returned table is deeply frozen.

luau
local data = store.get(player)
  • Returns: T

store.update(player, transform)

Deep-copies the profile and executes transform(data) on the mutable clone. If transform returns false, changes are discarded.

luau
local success = store.update(player, function(data)
  data.coins += 50
end)
  • Returns: boolean (true if updated, false if cancelled)

store.save(player)

Requests an immediate save for the player's session without waiting for autosave.

luau
store.save(player)

store.is_loaded(player)

Returns whether the player currently has an active, loaded session on this server.

luau
local loaded = store.is_loaded(player)
  • Returns: boolean

store.is_locked(user_id)

Checks whether an active distributed lock is held for the given user ID.

luau
local locked = store.is_locked(user_id)
  • Returns: boolean

store.on_close(player, callback)

Registers a callback invoked when the player's session closes. Returns a disconnect function.

luau
local disconnect = store.on_close(player, function(reason)
  print(`Session closed: {reason}`)
end)

Close Reasons: "manual" | "lock_lost" | "shutdown" | "stolen" | "save_unknown" | "transaction_unknown"

store.peek(user_id)

Reads offline data from DataStore without acquiring a lock. Applies template defaults and pending migrations.

luau
local data = store.peek(user_id)
  • Returns: T?

store.transact(participants, transform)

Executes an atomic transaction across multiple online or offline participants.

luau
local success = store.transact({ player_a, player_b }, function(states)
  states[tostring(player_a.UserId)].coins -= 10
  states[tostring(player_b.UserId)].coins += 10
end)
  • Parameters:
    • participants: { Player | number | string }
    • transform: (states: { [string]: T }) -> boolean?
  • Returns: boolean

store.send_global_update(user_id, data)

Appends an update payload to the target player's queue.

luau
store.send_global_update(user_id, { reward = "gift_box" })

store.erase(user_id)

Permanently removes all stored records, shards, and queued updates for a player. Fails if a session is currently active.

luau
store.erase(user_id)

store.list_loaded()

Returns an array of all Player instances with active sessions in this store.

luau
local active_players = store.list_loaded()
  • Returns: { Player }

store.get_session_info(player)

Returns metadata about the active session, or nil if not loaded.

luau
local info = store.get_session_info(player)
  • Returns: { key: string, is_dirty: boolean, is_saving: boolean, open_time: number, last_save_time: number, version: number }?

store.close()

Closes all sessions in this store and flushes pending saves.

luau
store.close()

Validator API

luau
local validator = lsd.validator

Primitive Rules

  • validator.boolean: Booleans (true / false).
  • validator.number: Finite numbers (rejects NaN and Inf).
  • validator.integer: Finite integers (value % 1 == 0).
  • validator.string: Valid UTF-8 strings.
  • validator.any: Any DataStore-serializable value subtree.

Structure Rules

  • validator.record(fields): Strict table with fixed string fields.
  • validator.list(item_rule): Contiguous 1-indexed array.
  • validator.map(value_rule): Open dictionary with string keys.
  • validator.optional(rule): Accepts nil or the inner rule.

Composition Rules

  • validator.literal(expected): Exact scalar equality match.
  • validator.enum(values): Value must match one of the items in the set.
  • validator.either(...rules): Ordered union; matches first passing rule.
  • validator.where(rule, predicate, [message]): Custom refinement constraint.

Compilation & Execution

  • validator.create(fields): Shorthand for validator.compile(validator.record(fields)).
  • validator.compile(root_rule): Compiles a rule into a validator function (value: T) -> (boolean, string?).
  • validator.check(checker, value): Safely tests a value with pcall, returning (boolean, string?).
  • validator.assert_valid(checker, value, context): Asserts validity or throws "{context}: {message}".

Last updated:

Released under the MIT License.