🍺 Buy me a beer

Redis

Non è "un database più veloce": è una cassetta degli attrezzi in RAM con strutture dati che un RDBMS non ha. Cache, sessioni, codeine, pub/sub, rate limiting — e i comandi giusti per non farlo esplodere in produzione.

"Ho lanciato KEYS * su 40 milioni di chiavi in produzione" — il modo più rapido per scoprire che Redis è single-threaded anche quando non vorresti che lo fosse.

01 / 13

Cos'è davvero Redis

REmote DIctionary Server: un archivio chiave-valore che vive (quasi sempre) tutto in RAM, con strutture dati molto più ricche di un semplice "stringa → stringa".

💡 I post-it sulla scrivania, non l'archivio in cantina

Un RDBMS come PostgreSQL (vedi la guida Database) è l'archivio in cantina: organizzato, durevole, con un registro che non perde nulla nemmeno se salta la corrente, ma per prendere un faldone devi scendere le scale. Redis è il blocco di post-it sulla tua scrivania: tutto a portata di mano, velocissimo da leggere e scrivere, ma se la scrivania prende fuoco (il processo muore) senza aver salvato una copia, i post-it non ci sono più. Redis non sostituisce l'archivio: gli sta accanto, per tutto quello che deve essere letto e scritto migliaia di volte al secondo senza scendere le scale ogni volta.

Perché è così veloce: single-threaded, e non è un difetto

Redis esegue i comandi uno alla volta su un singolo thread principale (dalla versione 6 in poi alcune operazioni di I/O sono multi-thread, ma l'esecuzione dei comandi resta single-threaded). Sembra una limitazione, mentre è il segreto della sua velocità: zero lock, zero context switch tra thread, zero complessità di concorrenza. Dato che tutto vive in RAM (niente attesa del disco) e ogni comando è pensato per essere O(1) o O(log n), un singolo core basta e avanza per centinaia di migliaia di operazioni al secondo.

⚠️ Il rovescio della medaglia: un comando lento (una scansione di una collezione enorme, uno script Lua pesante) blocca tutti gli altri client finché non finisce. Il capitolo 12 spiega come scovare questi colli di bottiglia prima che diventino un incidente.
Uso tipicoPerché Redis ci sta bene
CacheRisparmia query costose al database "vero", risposte in microsecondi
Session storeSessioni web condivise tra più server applicativi, con TTL nativo
Rate limitingContatori atomici con scadenza, perfetti per "max N richieste al minuto"
Code & job queueListe o Stream come coda di lavoro tra produttori e worker
LeaderboardSorted Set: classifiche ordinate per punteggio, aggiornate in tempo reale
Pub/SubNotifiche in tempo reale tra servizi, senza infrastruttura dedicata
02 / 13

Installazione & anatomia

Redis si installa in due minuti. Il config file un po' meno immediato, ma le opzioni che contano davvero sono poche.

📦 Installazione

Debian/Ubuntu
sudo apt install redis-server
sudo systemctl status redis-server
redis-cli ping   # risposta attesa: PONG

🔌 Connettersi

redis-cli
redis-cli                        # locale, porta di default
redis-cli -h 10.0.0.5 -p 6379 -a segreta
redis-cli -n 1                   # seleziona il DB numero 1 (0-15 di default)

📄 redis.conf: le opzioni che contano

/etc/redis/redis.conf
bind 127.0.0.1 -::1        # su quali interfacce ascolta (vedi cap. 11 per esporlo in rete)
port 6379
daemonize no                # su systemd resta no, e' systemd a gestire il processo
supervised systemd
dir /var/lib/redis          # dove finiscono i file di persistenza (RDB/AOF, cap. 5)
logfile /var/log/redis/redis-server.log
maxmemory 2gb                # limite di RAM utilizzabile (cap. 6)
maxmemory-policy allkeys-lru
requirepass segreta          # AUTH, vedi cap. 11
💡 Redis organizza i dati in 16 database numerati (0-15 di default, configurabile con databases), selezionabili con SELECT n o redis-cli -n n. Non sono "database" nel senso relazionale: sono solo namespace separati nello stesso processo, utili per non far collidere le chiavi di applicazioni diverse sulla stessa istanza.
03 / 13

Tipi di dato: il vero superpotere di Redis

La differenza rispetto a "un dizionario in RAM" è qui: ogni valore può essere una struttura dati ricca, non solo una stringa.

TipoCos'èComandi tipici
StringTesto, numeri, o dati binari (fino a 512MB)SET GET INCR APPEND
ListLista ordinata, ottima come coda/stackLPUSH RPUSH LRANGE LPOP
HashMappa campo→valore, come un "oggetto"HSET HGET HGETALL
SetInsieme di elementi unici, non ordinatoSADD SMEMBERS SINTER
Sorted Set (ZSET)Come un Set, ma ogni elemento ha un punteggio che lo ordinaZADD ZRANGE ZINCRBY
BitmapStringa trattata come vettore di bit, efficientissima per flagSETBIT GETBIT BITCOUNT
HyperLogLogConteggio approssimato di elementi unici, pochi byte fissiPFADD PFCOUNT
StreamLog append-only con consumer group, simile a un mini-KafkaXADD XREAD XGROUP

📋 Hash: un oggetto senza serializzare tutto

rappresentare un utente
HSET utente:42 nome "Mario" email "[email protected]" eta 34
HGET utente:42 email
HGETALL utente:42
HINCRBY utente:42 eta 1

🏆 Sorted Set: la classifica che si aggiorna da sola

leaderboard in tempo reale
ZADD classifica 1500 "mario" 2200 "luigi"
ZINCRBY classifica 300 "mario"
ZREVRANGE classifica 0 2 WITHSCORES   -- top 3, punteggio piu' alto prima
ZRANK classifica "mario"               -- posizione in classifica
📊 HyperLogLog è il più sorprendente dei tipi: conta elementi unici (es. "visitatori unici oggi") usando solo 12KB fissi, indipendentemente dal fatto che tu stia contando mille o un miliardo di elementi — con un errore tipico dello 0,81%. Il prezzo di questa magia: non puoi elencare gli elementi, solo contarli.
04 / 13

Gestione delle chiavi: TTL, SCAN, atomicità

Le operazioni trasversali a tutti i tipi: quanto vive una chiave, come cercarle senza bloccare tutto, e come restare atomici.

TTL: la scadenza nativa

expire, ttl, persist
SET sessione:abc123 "dati_utente" EX 3600   # scade tra 1 ora
EXPIRE sessione:abc123 7200                  # cambia la scadenza a 2 ore
TTL sessione:abc123                          # secondi rimanenti (-1 = mai, -2 = non esiste)
PERSIST sessione:abc123                      # rimuove la scadenza

Il TTL è il motivo per cui Redis è la scelta naturale per sessioni web e cache: la scadenza è gestita dal server stesso, senza bisogno di un job esterno che ripulisce i dati vecchi.

💥 KEYS * in produzione è un blocco totale, non solo una query lenta Essendo single-threaded (cap. 1), KEYS * su un database con milioni di chiavi blocca ogni altro client finché la scansione completa non finisce — secondi o minuti di sistema fermo. Usa sempre SCAN, che itera un cursore alla volta senza bloccare: SCAN 0 MATCH utente:* COUNT 100. Non è una best practice opzionale, è la differenza tra un comando innocuo e un incidente.

🔒 Atomicità: MULTI/EXEC e le operazioni native

Molti comandi Redis (INCR, SETNX, HINCRBY) sono già atomici da soli, proprio perché single-threaded: nessun altro client può "intromettersi" a metà. Per raggruppare più comandi in un'unica unità atomica si usa MULTI/EXEC (una transazione "ottimistica": mette in coda i comandi e li esegue tutti insieme, senza però un vero rollback se uno fallisce a runtime).

transazione semplice
MULTI
INCR contatore:visite
EXPIRE contatore:visite 86400
EXEC
💡 Per logica condizionale più complessa (leggi, decidi, scrivi, tutto atomicamente) lo strumento giusto sono gli script Lua (EVAL): girano interamente sul server, come un singolo comando atomico, senza round-trip multipli col client.
05 / 13

Persistenza: RDB vs AOF

Redis vive in RAM, ma questo non significa che i dati spariscano per forza a ogni riavvio. Due strategie, con compromessi opposti.

RDB (snapshot)AOF (Append-Only File)
Cosa salvaUna fotografia completa della memoria, a intervalliOgni comando di scrittura, in sequenza
Dati persi in caso di crashTutto quello dopo l'ultimo snapshot (minuti)Quasi nulla, dipende dalla policy fsync
Dimensione fileCompatto (binario, compresso)Più grande (log di comandi), ma si riscrive/comprime periodicamente
Velocità di restartVeloce (carica una fotografia)Più lento (riapplica il log)
Impatto in scritturaBasso (fork periodico)Più alto se fsync always

📸 RDB: la fotografia

redis.conf
save 900 1      # snapshot se >=1 chiave cambiata in 900s
save 300 10     # o >=10 chiavi cambiate in 300s
save 60 10000   # o >=10000 chiavi cambiate in 60s

Redis fa fork() del processo per scrivere lo snapshot senza bloccare le operazioni normali (copy-on-write): efficiente, ma su dataset enormi il fork stesso può causare un breve picco di latenza.

📜 AOF: il log di ogni scrittura

redis.conf
appendonly yes
appendfsync everysec   # default: compromesso ragionevole
-- appendfsync always : zero perdita dati, molto piu' lento
-- appendfsync no     : lascia decidere al SO, veloce ma rischioso

Il file AOF cresce continuamente; Redis lo riscrive periodicamente in forma compatta (BGREWRITEAOF) senza perdere lo storico delle chiavi attuali.

Dal Redis 4 in poi è comune usare entrambi insieme ("hybrid persistence"): AOF per la durabilità minuto per minuto, RDB come fotografia compatta per i restart e i backup. Se i tuoi dati in Redis sono solo cache facilmente ricostruibile dal database vero, puoi anche disabilitare tutto (save "") e vivere felice: dipende da quanto ti costa "ricalda" la cache da zero.
06 / 13

Memoria & eviction

Redis vive tutto in RAM: prima o poi la RAM finisce, e devi decidere cosa succede quando è piena.

📊 maxmemory-policy: cosa buttare via quando la RAM è piena

PolicyComportamento
noevictionRifiuta nuove scritture con errore (default). Sicuro ma può rompere l'app se non gestito
allkeys-lruButta via le chiavi usate meno di recente, tra tutte. Tipico per cache pura
volatile-lruCome sopra, ma solo tra le chiavi con un TTL impostato
allkeys-lfuButta via le chiavi usate meno frequentemente (non solo meno di recente)
volatile-ttlButta via prima le chiavi con TTL più vicino alla scadenza
⚠️ Se usi Redis anche come storage "importante" (non solo cache ricostruibile), noeviction è quasi sempre la scelta giusta: meglio un errore esplicito all'applicazione che perdere silenziosamente dati che pensavi persistenti. allkeys-* ha senso solo se ogni chiave è davvero rigenerabile da un'altra fonte.
quanta memoria sto usando davvero
redis-cli INFO memory
redis-cli MEMORY USAGE nomechiave
redis-cli --bigkeys    # scansiona e trova le chiavi piu' grandi per tipo
07 / 13

Pub/Sub & Streams

Due modi diversi di far comunicare servizi tramite Redis, con garanzie molto diverse tra loro.

📣 Pub/Sub: fuoco e dimentica

publish / subscribe
-- Un client in ascolto:
SUBSCRIBE notifiche

-- Un altro client pubblica:
PUBLISH notifiche "nuovo ordine #42"

Semplice ed efficace, ma senza persistenza: se nessun client è in ascolto in quel momento, il messaggio è perso per sempre. Va bene per notifiche "best effort" (invalidazione cache tra più server), non per nulla che deve essere garantito.

📜 Streams: il log che si può rileggere

XADD / XREAD / consumer group
XADD ordini '*' cliente_id 42 totale 150
XREAD COUNT 10 STREAMS ordini 0

-- Consumer group: piu' worker si dividono il carico
XGROUP CREATE ordini worker_grp '$'
XREADGROUP GROUP worker_grp worker1 COUNT 1 STREAMS ordini '>'
XACK ordini worker_grp <id-messaggio>

A differenza del Pub/Sub, gli Stream persistono i messaggi (soggetti comunque a RDB/AOF) e permettono a un consumer di riconnettersi e riprendere da dove aveva lasciato: molto più vicino a una vera coda di messaggi (concettualmente simile a Kafka, in scala più piccola).

💡 Se ti serve una vera coda di messaggi enterprise con garanzie forti su scala molto grande, RabbitMQ o Kafka restano scelte più mature. Redis Streams brilla quando hai già Redis in stack e non vuoi aggiungere un altro pezzo di infrastruttura per un caso d'uso di media scala.
08 / 13

Pattern d'uso: cache, lock, rate limiting

Le ricette pratiche che coprono il 90% di quello per cui la gente installa Redis.

💾 Cache-aside: il pattern più comune in assoluto

pseudocodice applicativo
valore = redis.GET("prodotto:42")
if valore is None:
    valore = database.query("SELECT * FROM prodotti WHERE id=42")
    redis.SET("prodotto:42", valore, EX=300)   # cache per 5 minuti
return valore

L'applicazione controlla prima la cache; solo se manca ("cache miss") interroga il database "vero" e ripopola Redis. Semplice, ma richiede di pensare a come invalidare la chiave quando il dato cambia (es. DEL prodotto:42 dopo un UPDATE).

Rate limiting con INCR + EXPIRE

max 100 richieste al minuto per utente
MULTI
INCR rate:utente42:2026-07-06T14:32
EXPIRE rate:utente42:2026-07-06T14:32 60
EXEC
-- se il risultato di INCR > 100, rifiuta la richiesta

🔒 Distributed lock: SET NX EX

lock semplice ad esclusione mutua
SET lock:job42 "worker-1" NX EX 30
-- NX = solo se non esiste gia': solo un worker "vince"
-- EX 30 = si autolibera se il worker crasha senza rilasciarlo
DEL lock:job42   -- rilascio esplicito a lavoro finito
⚠️ Il distributed lock "semplice" ha dei limiti noti Il pattern SET NX EX funziona bene per la maggior parte dei casi, ma non è a prova di ogni scenario patologico (failover del nodo Redis proprio mentre il lock è attivo, clock drift). L'algoritmo Redlock proposto da Redis per i casi multi-nodo è stato oggetto di un noto dibattito tecnico pubblico tra lo stesso autore di Redis e altri esperti di sistemi distribuiti sulla sua reale robustezza in scenari di clock drift e GC pause. Se un lock che fallisce causa danni seri (non solo un piccolo doppio-processamento), valuta uno strumento pensato apposta per il consenso distribuito (etcd, ZooKeeper) invece di forzare Redis a fare quel lavoro.
09 / 13

Replica & Sentinel

Un solo nodo Redis è anche un solo punto di guasto (vedi la guida Alta Affidabilità per il concetto generale). Ecco come Redis lo risolve.

🔄 Replica asincrona master-replica

agganciare un replica
# Sul nodo replica, a runtime:
REPLICAOF 10.0.0.10 6379

# Oppure in redis.conf, permanente:
replicaof 10.0.0.10 6379
masterauth segreta

# Tornare master (es. dopo un failover manuale)
REPLICAOF NO ONE

La replica è asincrona: il master non aspetta conferma dal replica prima di rispondere al client, quindi in caso di crash improvviso del master puoi perdere le ultimissime scritture non ancora propagate. È un compromesso deliberato per non sacrificare la latenza, coerente con l'uso tipico di Redis (cache, non registro bancario).

🛡️ Redis Sentinel: failover automatico

Sentinel è un processo separato (tipicamente 3 o più istanze, per avere quorum come nella guida Alta Affidabilità) che monitora master e replica, e se il master smette di rispondere, promuove automaticamente un replica a nuovo master e riconfigura gli altri replica di conseguenza.

sentinel.conf essenziale
sentinel monitor mymaster 10.0.0.10 6379 2   # 2 = quorum minimo per dichiarare il master giu'
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel auth-pass mymaster segreta
i client chiedono a Sentinel chi è il master ADESSO
redis-cli -p 26379 SENTINEL get-master-addr-by-name mymaster
💡 I client applicativi non si connettono direttamente a un IP fisso: interrogano Sentinel per sapere chi è il master corrente (o usano una libreria client che lo fa in automatico). È concettualmente lo stesso principio del quorum visto nella guida Alta Affidabilità, applicato specificamente a Redis.
10 / 13

Redis Cluster: quando un nodo solo non basta più

Sentinel risolve la disponibilità. Redis Cluster risolve un problema diverso: i dati non entrano più nella RAM di una sola macchina.

🏷️ Hash slot: 16384 caselle, distribuite tra i nodi

Redis Cluster divide lo spazio delle chiavi in 16384 hash slot fissi. Ogni chiave viene assegnata a uno slot tramite CRC16(chiave) % 16384, e ogni nodo del cluster è responsabile di un sottoinsieme di slot. Un client che scrive una chiave viene automaticamente indirizzato (o reindirizzato, con un MOVED) al nodo giusto.

creare un cluster minimo (3 master + 3 replica)
redis-cli --cluster create \
  10.0.0.1:6379 10.0.0.2:6379 10.0.0.3:6379 \
  10.0.0.4:6379 10.0.0.5:6379 10.0.0.6:6379 \
  --cluster-replicas 1

redis-cli -c -p 6379 cluster info
redis-cli -c -p 6379 cluster nodes
⚠️ Operazioni multi-chiave richiedono che le chiavi stiano nello stesso slot Comandi come MGET su chiavi sparse su slot diversi falliscono in Redis Cluster. La soluzione: le hash tag — racchiudi la parte "da hashare" tra graffe, es. ordini:{cliente42}:lista e ordini:{cliente42}:totale finiscono sempre sullo stesso slot perché Redis hasha solo la parte tra {}.
💡 Non serve il Cluster "per sicurezza": serve quando il dataset non entra più comodamente nella RAM di un solo nodo, o quando il throughput richiesto supera quello che un singolo core può gestire. Per la disponibilità da sola, Sentinel (cap. 9) è più semplice da operare e spesso sufficiente.
11 / 13

Sicurezza

Redis storicamente si fidava della rete su cui girava. Su Internet aperto, questa fiducia è costata caro a migliaia di istanze.

💥 Redis senza password su Internet è una storia vera, ripetuta migliaia di volte Per anni Redis non richiedeva autenticazione di default e molte immagini Docker/cloud lo esponevano per errore sulla porta 6379 pubblica: il risultato sono state ondate di attacchi automatizzati che scrivevano chiavi SSH nell'authorized_keys della macchina host tramite CONFIG SET dir + SAVE, o cifravano i dati per riscatto. La lezione non è "Redis è insicuro": è che un datastore pensato per reti fidate va sempre messo dietro un firewall, mai esposto direttamente.

🔐 Le basi, sempre

redis.conf minimo sicuro
bind 127.0.0.1 10.0.0.5   # MAI 0.0.0.0 su una rete non fidata
protected-mode yes
requirepass una-password-lunga-e-vera
rename-command FLUSHALL ""    # disabilita comandi distruttivi se non servono
rename-command CONFIG ""

👤 ACL: utenti granulari (Redis 6+)

utente con permessi limitati
ACL SETUSER app_readonly on >segreta \
  ~cache:* +get +exists -@all
ACL LIST
ACL WHOAMI

Prima di Redis 6 esisteva solo requirepass (tutto o niente). Le ACL permettono utenti dedicati con permessi ristretti a comandi e chiavi specifiche — lo stesso principio del minimo privilegio visto per i database relazionali.

💡 Per connessioni tra reti non fidate (es. tra datacenter diversi), abilita TLS (supportato nativamente dal Redis 6 in poi) invece di affidarti solo a requirepass: senza cifratura, la password stessa viaggia in chiaro sulla rete.
12 / 13

Performance & troubleshooting

Redis è velocissimo finché non trovi il comando, la chiave enorme, o lo script Lua che lo rallenta per tutti.

🔍 SLOWLOG: chi ha rallentato il server

trovare i comandi lenti
CONFIG SET slowlog-log-slower-than 10000  -- microsecondi (10ms)
SLOWLOG GET 10
SLOWLOG RESET

👀 MONITOR: guardare tutto in tempo reale

debug interattivo
redis-cli MONITOR

Mostra ogni comando eseguito, in tempo reale. Utilissimo per il debug puntuale, ma non lasciarlo mai acceso in produzione a lungo: l'overhead di stampare ogni comando rallenta il server sotto carico reale.

📊 INFO: lo stato di salute in un colpo solo

le sezioni che contano
redis-cli INFO stats     # hit/miss della cache, connessioni, comandi al secondo
redis-cli INFO memory    # uso RAM, frammentazione
redis-cli INFO replication # stato master/replica, lag
redis-cli --latency      # latenza media percepita in tempo reale
⚠️ Un keyspace_hit_rate basso (in INFO stats: keyspace_hits vs keyspace_misses) su una cache spesso significa TTL troppo corti, o chiavi che cambiano così spesso da rendere la cache quasi inutile — vale la pena guardarlo prima di aggiungere più RAM pensando che risolva da solo.

✓ Buone abitudini

  • SCAN invece di KEYS, sempre, in produzione
  • TTL su ogni chiave che non deve vivere per sempre
  • Monitorare maxmemory e la eviction policy scelta consapevolmente
  • redis-cli --bigkeys periodico per scovare chiavi anomale

✗ Errori classici

  • Una singola chiave Hash/List con milioni di campi ("big key")
  • Script Lua pesanti che bloccano il thread principale
  • MONITOR lasciato acceso su un'istanza di produzione
  • Nessun limite di memoria (maxmemory non impostato): rischio OOM del sistema
13 / 13

Cheat Sheet & Glossario

Tutto quello che serve, su una pagina. Bookmark questa sezione e dimentica il resto.

🔑 Chiavi & String

i comandi di ogni giorno
SET k v EX 60
GET k
DEL k
EXISTS k
TTL k
SCAN 0 MATCH pattern:* COUNT 100
INCR contatore

📋 Strutture dati

list, hash, set, zset
LPUSH lista v1 v2   /   LRANGE lista 0 -1
HSET h campo v      /   HGETALL h
SADD s v1 v2        /   SMEMBERS s
ZADD z 10 v1        /   ZRANGE z 0 -1 WITHSCORES

🔄 Replica & cluster

HA & scaling
REPLICAOF host porta
INFO replication
redis-cli -p 26379 SENTINEL get-master-addr-by-name mymaster
redis-cli --cluster create ...

🔍 Diagnostica

salute & performance
INFO stats
SLOWLOG GET 10
redis-cli --bigkeys
redis-cli --latency
MEMORY USAGE chiave

📚 Glossario essenziale

  • Key-value store — database che mappa chiavi a valori, senza schema relazionale
  • Single-threaded — esegue un comando alla volta, niente lock di concorrenza
  • TTL — tempo di vita residuo di una chiave prima della scadenza automatica
  • RDB — snapshot binario periodico dell'intero dataset
  • AOF — log di ogni comando di scrittura, per durabilità più fine
  • Eviction policy — regola che decide cosa buttare quando la RAM è piena
  • LRU / LFU — usato meno di recente / usato meno frequentemente
  • Pub/Sub — messaggistica "fuoco e dimentica", non persistente
  • Stream — log persistente con consumer group, rileggibile
  • Sentinel — processo di monitoraggio e failover automatico
  • Redis Cluster — sharding automatico su più nodi via hash slot
  • Hash slot — una delle 16384 partizioni fisse dello spazio chiavi nel Cluster
  • Hash tag — parte di chiave tra {} usata per forzare lo stesso slot
  • MULTI/EXEC — transazione: comandi accodati ed eseguiti insieme
  • Lua scripting (EVAL) — logica atomica eseguita lato server
  • ACL — permessi granulari per utente, dal Redis 6
  • HyperLogLog — struttura probabilistica per conteggi unici approssimati

📚 Risorse

  • redis.io/docs — documentazione ufficiale, comandi e tipi di dato
  • redis.io/commands — riferimento completo di ogni comando
  • Redis University — corsi gratuiti ufficiali
  • "Redis in Action" — libro classico sui pattern d'uso pratici

🔗 Guide collegate

  • PostgreSQL, MySQL & SQL — il database "vero" che Redis affianca, non sostituisce
  • Alta Affidabilità — quorum e failover, applicati qui da Sentinel
  • Docker — far girare Redis in container con persistenza su volume
  • Networking — firewall e VPN per non esporre mai Redis su Internet
  • Linux Admin — systemd e il resto dell'infrastruttura sotto
Regola finale dello svogliato — usa SCAN invece di KEYS, metti sempre un TTL su quello che può scadere, non esporre mai Redis direttamente su Internet, e decidi consapevolmente se ti serve davvero persistere i dati o se è solo cache ricostruibile. Il resto — Cluster, Streams, Lua scripting — lo aggiungi quando il problema concreto arriva, non prima.