Introduction
Google Cloud Spanner est une base de données relationnelle entièrement gérée, scalable horizontalement à l'échelle mondiale, avec ACID complet et forte cohérence. Contrairement aux bases traditionnelles comme PostgreSQL qui peinent au-delà de quelques To, Spanner gère des pétaoctets sans downtime, idéal pour les apps fintech, e-commerce ou IoT nécessitant haute disponibilité.
Ce tutoriel beginner vous guide pas à pas : de l'installation du SDK à l'exécution de queries SQL via Node.js. Vous apprendrez à créer une instance, une base, des tables, insérer des données et interroger en temps réel. À la fin, vous aurez un projet fonctionnel bookmarkable. Prévoir 30-45 min et un compte GCP gratuit (300$ crédit). Pourquoi 2026 ? Nouvelles features comme l'intégration Gemini pour queries AI et tarifs optimisés pour dev.
Avantages concrets : Latence <10ms globale, auto-scaling, backups automatisés. Parfait pour remplacer Cassandra ou BigQuery en OLTP.
Prérequis
- Compte Google Cloud Platform (GCP) actif avec facturation activée (crédit gratuit 300$).
- Node.js 20+ installé.
- gcloud CLI version 450+.
- Connaissances basiques TypeScript/JavaScript et SQL.
- Éditeur de code (VS Code recommandé).
Activer l'API et installer le SDK
# Authentifier gcloud
gcloud auth login
gcloud config set project VOTRE-PROJET-ID # Remplacez par votre GCP project ID
gcloud services enable spanner.googleapis.com
gcloud components install beta
# Installer le client Node.js
mkdir spanner-tutorial && cd spanner-tutorial
npm init -y
npm install @google-cloud/spanner typescript @types/node ts-node
# Compiler TS (optionnel)
npm install -D tscCe script active l'API Spanner, authentifie gcloud et initialise un projet Node.js avec le client officiel. Remplacez VOTRE-PROJET-ID par votre project GCP (trouvé dans console.cloud.google.com). Les pièges : oublier l'auth ou le project ID cause des erreurs 403/404.
Configurer l'environnement
Une fois le setup bash exécuté, vérifiez avec gcloud projects list. Téléchargez vos credentials service account si besoin (IAM > Service Accounts > Créer clé JSON), mais gcloud auth suffit pour dev local. Créez un fichier .env pour les IDs : PROJECT_ID=votreprojet, INSTANCE_ID=test-instance, DATABASE_ID=test-db. Spanner est multi-régional par défaut pour haute disponibilité.
Créer l'instance Spanner
# Créer une instance régionale (config=1 pour 1000 processing units, ajustez pour prod)
gcloud spanner instances create $INSTANCE_ID \
--config=nam-eur3 \
--description="Instance tutorial" \
--nodes=1
# Vérifier
sleep 60
gcloud spanner instances describe $INSTANCE_ID
# Variables d'env (ajoutez à .env)
export INSTANCE_ID=test-instanceCrée une instance minimale (1 nœud, ~100$/mois, gratuit en dev). nam-eur3 est Europe ; listez configs avec gcloud spanner instance-configs list. Piège : attente 1-2min pour provisioning ; ignorer cause timeouts.
Créer la base de données
L'instance est le conteneur scalable ; la DB est logique dedans. Utilisez DDL SQL pour schémas. Pensez Spanner comme SQL + NoSQL : interleaved tables pour hiérarchies (ex: users > orders).
Créer la base et la table
# Créer la DB
gcloud spanner databases create $DATABASE_ID --instance=$INSTANCE_ID --ddl='CREATE TABLE Users (
UserId INT64 NOT NULL,
Email STRING(256) NOT NULL,
Name STRING(100),
) PRIMARY KEY(UserId)' \
--ddl='CREATE TABLE Orders (
OrderId INT64 NOT NULL,
UserId INT64 NOT NULL,
Product STRING(100),
Amount FLOAT64,
) PRIMARY KEY(OrderId),
INTERLEAVE IN PARENT Users ON DELETE CASCADE'
# Vérifier
databases list --instance=$INSTANCE_IDCrée DB avec tables Users/Orders. Interleave lie Orders à Users pour jointures rapides/low-latency. FLOAT64 pour montants ; NOT NULL évite NULLs. Piège : syntaxe DDL stricte, testez en console Spanner.
Client Node.js pour insertions
Analogie : Comme un pilote DB, le client gère sessions/transactions. Spanner supporte mutations batch pour perf.
Insérer des données
import { Spanner } from '@google-cloud/spanner';
const spanner = new Spanner({
projectId: process.env.PROJECT_ID!,
});
const instance = spanner.instance(process.env.INSTANCE_ID!);
const database = instance.database(process.env.DATABASE_ID!);
async function insertData() {
const tx = await database.runTransaction();
try {
await tx.insert('Users', {
UserId: 1n,
Email: 'alice@example.com',
Name: 'Alice',
});
await tx.insert('Orders', {
OrderId: 101n,
UserId: 1n,
Product: 'Laptop',
Amount: 999.99,
});
await tx.commit();
console.log('Données insérées');
} catch (err) {
await tx.rollback();
console.error(err);
}
}
insertData();Insère en transaction ACID. BigInt (1n) pour INT64. RunTransaction assure cohérence. Piège : oublier commit/rollback crash ; utilisez async/await partout.
Exécuter des queries
Queries SQL standard + extensions Spanner (ARRAY, STRUCT). Pagination avec LIMIT/OFFSET pour scale.
Lire et query les données
import { Spanner } from '@google-cloud/spanner';
const spanner = new Spanner({ projectId: process.env.PROJECT_ID! });
const instance = spanner.instance(process.env.INSTANCE_ID!);
const database = instance.database(process.env.DATABASE_ID!);
async function queryData() {
const [[usersRow]] = await database.run({
sql: `SELECT u.UserId, u.Name, ARRAY_AGG(o.Product) AS Products
FROM Users u
LEFT JOIN Orders o ON u.UserId = o.UserId
GROUP BY u.UserId, u.Name`,
});
console.log('Users et orders:', usersRow);
// Single row
const [order] = await database.run({
sql: 'SELECT * FROM Orders WHERE OrderId = @id',
params: { id: 101n },
types: { id: 'INT64' },
});
console.log('Order:', order);
}
queryData();Query JOIN avec ARRAY_AGG (Spanner-specific). Params/types prévient SQL injection. Piège : types obligatoires pour params ; sans, erreur parsing.
Nettoyage et script complet
import { Spanner } from '@google-cloud/spanner';
import dotenv from 'dotenv';
dotenv.config();
const spanner = new Spanner({ projectId: process.env.PROJECT_ID! });
const instance = spanner.instance(process.env.INSTANCE_ID!);
const database = instance.database(process.env.DATABASE_ID!);
async function main() {
// Insert
const tx = await database.runTransaction();
try {
await tx.insert('Users', { UserId: 2n, Email: 'bob@example.com', Name: 'Bob' });
await tx.insert('Orders', { OrderId: 102n, UserId: 2n, Product: 'Phone', Amount: 599.99 });
await tx.commit();
} catch (err) {
await tx.rollback();
console.error('Insert failed:', err);
return;
}
// Query
const [rows] = await database.run({
sql: 'SELECT * FROM Users u JOIN Orders o ON u.UserId = o.UserId',
});
console.table(rows);
}
main().catch(console.error);
// Exécuter: ts-node full-app.tsScript tout-en-un : dotenv pour env, insert + query. Console.table pour visu. Piège : .env ignoré sans dotenv ; toujours catch global.
Bonnes pratiques
- Toujours transactions : Pour multi-mutations, ACID garanti.
- Interleave tables : Pour relations 1:N, réduit latence joins 10x.
- Index secondaires :
CREATE INDEX ON Orders(UserId)pour queries rapides. - Monitoring : Utilisez Cloud Monitoring pour CPU/QPS ; auto-scale nodes.
- Backup auto : Point-in-time recovery jusqu'à 7 jours gratuit.
Erreurs courantes à éviter
- Oubli types params : Query crash avec 'Invalid type'. Toujours spécifiez { id: 'INT64' }.
- Pas d'attente provisioning : Instance/DB prend 2-5min ; poll avec describe.
- Quota dépassé : 1 instance gratuite ; upgrade pour prod.
- INT64 comme number : Utilisez BigInt, JS number déborde >2^53.
Pour aller plus loin
- Docs officielles : Cloud Spanner Node.js.
- Avancé : ReadWriteTransactions, Backup/Restore.
- Découvez nos formations Learni sur Google Cloud pour certif CKAD/Spanner expert.
- Projet open-source : Clonez ce tuto sur GitHub et fork pour vos apps.