Skip to content

KV Storage

Every TMA.sh project includes a key-value store. No database setup, no connection strings — import the SDK and start reading and writing data.

import { createTMA } from '@tma.sh/sdk';
const tma = createTMA({ projectId: 'your-project-id' });

Store any JSON-serializable value:

await tma.kv.set('user:123:preferences', {
theme: 'dark',
language: 'en',
notifications: true,
});

Setting a key that already exists overwrites the previous value.

Retrieve a value by key. Returns null if the key does not exist:

const prefs = await tma.kv.get('user:123:preferences');
// { theme: 'dark', language: 'en', notifications: true }

Remove a key and its value:

await tma.kv.remove('user:123:preferences');

Removing a key that does not exist is a no-op.

Retrieve all keys matching a prefix:

const result = await tma.kv.list('user:123:');
const keyNames = result.keys.map(k => k.name);
// ['user:123:preferences', 'user:123:scores', 'user:123:inventory']

The list() method returns an object with keys (an array of { name: string } objects) and list_complete (a boolean indicating whether all matching keys have been returned). Use colons as separators to create a natural key hierarchy. Fetch individual values with kv.get().

PropertyLimit
Max value size128 KB
Max key size512 bytes
ConsistencyEventually consistent (~60s)

Values are stored as JSON. The 128 KB limit applies to the serialized JSON string. Keys must be valid UTF-8 strings.

Eventually consistent means that after a write, subsequent reads from different edge locations may return the previous value for up to 60 seconds. Reads from the same location that performed the write are immediately consistent.

Use colon-separated segments for structured keys:

{entity}:{id}:{field}

Examples:

user:123:preferences
user:123:scores
leaderboard:global
session:abc123
feature:dark-mode
cache:api:weather:london

This convention makes prefix-based listing predictable and keeps your keyspace organized.

KV storage works well for:

  • User preferences — theme, language, notification settings
  • Feature flags — toggle features per user or globally
  • Leaderboards — store scores keyed by user ID, list by prefix
  • Session data — temporary state between page loads
  • Cached API responses — store third-party API results with a TTL key pattern

KV storage is not a database. For the following use cases, connect an external database like Supabase or Turso instead:

  • Relational data — queries that join tables or filter on multiple columns
  • Transactions — operations that must succeed or fail atomically
  • Complex queries — full-text search, aggregations, sorting by multiple fields
  • Strong consistency — reads that must always return the latest write

See the Authentication page for how to connect TMA.sh JWTs to Supabase.

In API routes, use the createKV() helper from @tma.sh/sdk/server for a typed wrapper around the KV binding. See Server Helpers for details.