Skip to content
KV from PHP

KV from PHP

ePHPm’s built-in KV store is reachable two ways from PHP:

  1. SAPI functionsephpm_kv_* calls into the embedded store directly. ~100 ns per op, zero serialization.
  2. RESP protocol — any Redis client (Predis, phpredis) connects to the embedded RESP listener. ~10–100 µs per op.

The store is the same in both cases. Use SAPI for hot paths; use RESP when you need portability or Redis-style commands.

SAPI functions

No external dependency. Available as native PHP functions whenever PHP is running inside ePHPm.

ephpm_kv_set("greeting", "hello");
$greeting = ephpm_kv_get("greeting");          // "hello"
$missing  = ephpm_kv_get("nope");              // null

ephpm_kv_exists("greeting");                   // 1
ephpm_kv_del("greeting");                      // 1
ephpm_kv_exists("greeting");                   // 0

// Counters
ephpm_kv_incr("page:views", 1);                // 1
ephpm_kv_incr("page:views", 5);                // 6

// TTL (in milliseconds)
ephpm_kv_set("session:abc", "data");
ephpm_kv_expire("session:abc", 60_000);        // 60 seconds
ephpm_kv_pttl("session:abc");                  // ~60000
// returns -1 if no expiry, -2 if missing

When to use SAPI

  • High-frequency operations (logging, hit counters, rate limit hot path)
  • Simple key/value patterns
  • You don’t care about portability to standalone Redis

RESP protocol (Predis / phpredis)

Enable the listener in ephpm.toml:

[kv.redis_compat]
enabled = true
listen = "127.0.0.1:6379"   # default
# password = "..."           # optional AUTH

Then connect like any Redis server:

$redis = new Predis\Client('tcp://127.0.0.1:6379');

$redis->set('greeting', 'hello');
$redis->get('greeting');

$redis->setex('session:abc', 60, json_encode($data));
$count = $redis->incr('page:views');

Supported commands

GroupCommands
StringsGET, SET, SETEX, MGET, MSET, SETNX, INCR, DECR, INCRBY, DECRBY, APPEND, STRLEN, GETSET
KeysDEL, EXISTS, EXPIRE, PEXPIRE, PERSIST, TTL, PTTL, TYPE, KEYS, DBSIZE, FLUSHDB, FLUSHALL, RENAME
ConnectionPING, ECHO, SELECT, QUIT, COMMAND, INFO, AUTH

Not implemented: hashes, lists, sets, transactions, SCAN, pub/sub. ePHPm targets the cache + counter + session use case — if you need full Redis, run actual Redis.

Multi-tenant note

The RESP listener exposes the whole store with no per-vhost filtering. In multi-tenant deployments ([server] sites_dir = ...) keep [kv.redis_compat] enabled = false and use the SAPI functions, which are automatically namespaced per virtual host. ePHPm derives a per-site password from the master [kv] secret and injects it into PHP’s $_ENV as EPHPM_REDIS_PASSWORD.

Common patterns

Cache-aside

$key = "cache:user:{$id}";
$cached = ephpm_kv_get($key);
if ($cached === null) {
    $cached = expensive_lookup($id);
    ephpm_kv_set($key, json_encode($cached));
    ephpm_kv_expire($key, 5 * 60 * 1000);   // 5 minutes
}
return json_decode($cached, true);

Token-bucket rate limit

$key   = "ratelimit:{$ip}";
$count = ephpm_kv_incr($key, 1);
if ($count === 1) {
    ephpm_kv_expire($key, 60_000);          // first request opens a 60s window
}
return $count <= $max_per_minute;

Session storage

ephpm_kv_set("session:{$id}", json_encode($data));
ephpm_kv_expire("session:{$id}", 3600 * 1000);  // 1 hour

Configuration

[kv]
memory_limit = "256MB"
eviction_policy = "allkeys-lru"   # or noeviction / volatile-lru / allkeys-random
compression = "none"              # or gzip / brotli / zstd
compression_level = 6
compression_min_size = 1024       # bytes — values below this are stored raw

[kv.redis_compat]
enabled = false                   # turn on the RESP listener
listen = "127.0.0.1:6379"
# password = "..."                # AUTH required when set

See Configuration reference for every key.

See also