---
title: "Déployer une API Node.js et PostgreSQL par MCP, avec while.sh"
url: https://while.sh/fr/guides/api-node-postgresql/
author: "Aloïs Oddon, cofondateur de Nextmap"
updated: 2026-11-02
---

# Mettre en ligne une API Node.js et sa base PostgreSQL depuis votre agent IA, par MCP

Votre agent IA sait déjà écrire votre API Node.js. Branché à while par MCP, il la met aussi en ligne, avec sa base PostgreSQL sauvegardée chaque jour, et vous ne touchez à aucun serveur.

## Prérequis

- Une API Node.js.
- Un agent IA qui travaille dans un terminal : Claude Code, Codex, Cursor ou Gemini CLI.

## Étape 1 : Donnez ces instructions à votre agent

Ouvrez votre agent dans le dossier de votre API, et collez-lui ces instructions :

```text titre="Instructions"
Connecte-toi à while avec mon compte (while.sh/agents), puis mets mon appli en ligne.
```

Sans compte, votre agent met votre API en ligne à l'essai, en une demande. Pour la garder, ouvrez le lien qu'il vous donne et créez votre compte.

Avec votre compte, votre agent ajoute lui-même le serveur MCP de while. S'il vous le demande, relancez-le. Au premier appel à while, une page s'ouvre dans votre navigateur. Dans Claude Code, si elle ne s'ouvre pas, tapez /mcp, choisissez while, puis Authenticate. Sur cette page, choisissez votre appli, ou « Une nouvelle appli », puis cliquez sur Autoriser.

## Étape 2 : Ouvrez votre API

Votre agent vous donne l'adresse de votre API, par exemple `https://mon-api.while.cloud`.

## Ce que fait votre agent

Il lit les règles d'une appli sur while, comme écouter sur `PORT` et répondre 200 sur `/health`, puis écrit while.yaml à la racine de votre API :

```yaml titre="while.yaml"
apiVersion: while/v1
project: mon-api
services:
  - name: web
    port: 3000
databases:
  - name: main
```

Les deux dernières lignes ajoutent une base PostgreSQL. Son adresse, mot de passe compris, arrive à votre API dans `DATABASE_URL`. node-postgres la lit telle quelle (source 1), comme dans cette API Express essayée sur while :

```js titre="server.js"
import express from 'express';
import pg from 'pg';

const db = new pg.Pool({ connectionString: process.env.DATABASE_URL });
await db.query('CREATE TABLE IF NOT EXISTS visites (id serial PRIMARY KEY, cree_le timestamptz DEFAULT now())');

const app = express();
app.get('/health', (_req, res) => res.send('ok'));
app.get('/', async (_req, res) => {
  await db.query('INSERT INTO visites DEFAULT VALUES');
  const { rows } = await db.query('SELECT count(*)::int AS n FROM visites');
  res.send(`visites : ${rows[0].n}`);
});
app.listen(process.env.PORT || 3000, '0.0.0.0');
```

Il envoie ensuite le code, qui est construit, testé, puis mis en ligne.

## Choisir la version de PostgreSQL

> Vous, à votre agent : Crée la base sous PostgreSQL 18.

La version se choisit à la création : PostgreSQL 17 par défaut, la 16 ou la 18 avec `version` dans while.yaml :

```yaml titre="while.yaml"
databases:
  - name: main
    version: "18"
```

## Prévoir l'espace disque

> Vous, à votre agent : Crée la base avec 10 Gio de disque.

Le disque se choisit à la création de la base, avec `size` : 1 Gio par défaut. Demandez-le avant la première mise en ligne.

```yaml titre="while.yaml"
databases:
  - name: main
    size: 10Gi
```

## Utiliser Prisma avec PostgreSQL

> Vous, à votre agent : Utilise Prisma pour créer et migrer les tables.

Votre agent écrit le schéma et fait jouer la migration au démarrage de l'API. Prisma lit l'adresse de la base dans `DATABASE_URL` :

```prisma titre="prisma/schema.prisma"
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}
```

```json titre="package.json (extrait)"
"type": "module",
"scripts": {
  "build": "prisma generate",
  "start": "prisma migrate deploy && node server.js"
},
"dependencies": {
  "@prisma/client": "^6.1.0",
  "prisma": "^6.1.0"
}
```

Prisma va dans `dependencies` : l'API en ligne est installée sans les `devDependencies`. Inutile d'ajouter `?pgbouncer=true` à l'adresse : PgBouncer suit les requêtes préparées.

Votre agent ne déclare pas de `directUrl` : l'adresse directe de la base n'est donnée qu'aux tâches, et Prisma s'arrêterait au démarrage avec l'erreur P1012.

## Interroger PostgreSQL depuis votre agent, par MCP

> Vous, à votre agent : Combien de visites aujourd'hui ?

Votre agent lit votre base en SQL par le serveur MCP de while, avec vos droits sur les données, sans pouvoir y écrire. Chaque requête est notée au journal de while, ses valeurs remplacées par $1, $2…

## Exporter une table en CSV

> Vous, à votre agent : Exporte la table visites en CSV.

Votre agent écrit la table dans un fichier CSV, avec les mêmes droits que pour la lire.

## Trouver les requêtes lentes

> Vous, à votre agent : Quelles requêtes ralentissent la base ?

Votre agent lit les requêtes les plus fréquentes et les plus lentes de votre base, relevées par pg_stat_statements.

## Changer la taille de la base

> Vous, à votre agent : Passe la base en taille M.

Votre agent change `compute` dans while.yaml. Avant le changement, il voit ce qu'il coûte en plus par mois. La base redémarre ensuite, en une quinzaine de secondes.

| Taille (`compute`) | Processeur | Mémoire | Clients en même temps | Prix, hors taxes |
|---|---|---|---|---|
| S, par défaut | 0,1 vCPU | 256 Mo, jusqu'à 1 Go | 200 | 5 € par mois |
| M | 0,5 vCPU | 1 Go | 400 | 17 € par mois |
| L | 1 vCPU | 4 Go | 600 | 65 € par mois |
| XL | 2 vCPU | 8 Go | 800 | 150 € par mois |

```yaml titre="while.yaml"
databases:
  - name: main
    compute: M
```

## Ajouter une instance de secours

> Vous, à votre agent : Ajoute une instance de secours à la base.

Avec `instances: 2`, une seconde instance est tenue à jour en continu, sur son propre disque, et prend le relais si la première tombe. Avec l'offre Entreprise, une base de production a deux instances par défaut.

## Sauvegarder avant un changement

> Vous, à votre agent : Fais une sauvegarde avant la migration.

Votre agent lance une sauvegarde, aussitôt suivie d'un essai : une base jetable en naît, et ses tables sont relues. Chaque base est aussi sauvegardée tous les jours, et son journal est archivé en continu.

## Revenir à une sauvegarde ou à une heure précise

> Vous, à votre agent : Remets la base comme hier à 18 h.

Votre base revient à une sauvegarde ou à un instant précis, dans la limite de leur conservation : 14 jours. En production, votre agent vous donne un lien : la base ne revient qu'une fois la restauration validée, par vous ou par un administrateur selon vos droits. Une sauvegarde de sûreté part avant, puis la base restaurée prend la place de l'ancienne.

## Comprendre une mise en ligne qui échoue

> Vous, à votre agent : Pourquoi la mise en ligne a échoué ?

Votre agent reçoit l'erreur et les dernières lignes du journal de construction. Vos tests tournent pendant la construction : s'ils échouent, votre API garde sa version d'avant.

Par exemple, `connect ECONNREFUSED 127.0.0.1:5432` : vos tests cherchent une base, qui n'est pas branchée pendant la construction. Votre agent les écrit pour qu'ils passent sans elle, ou les coupe :

```yaml titre="while.yaml"
services:
  - name: web
    port: 3000
    build:
      skip_tests: true
```

## Régler la session derrière PgBouncer

`DATABASE_URL` passe par PgBouncer en mode transaction : chaque transaction peut prendre une autre connexion. Un `SET` hors transaction ne dure que sa requête. Pour régler la session, utilisez `SET LOCAL` dans une transaction :

```js titre="server.js"
const client = await db.connect();
try {
  await client.query('BEGIN');
  await client.query("SET LOCAL statement_timeout = '5s'");
  await client.query('SELECT count(*) FROM visites');
  await client.query('COMMIT');
} catch (e) {
  await client.query('ROLLBACK');
  throw e;
} finally {
  client.release();
}
```

Ce qui a besoin de la session entière, comme `pg_restore` ou une migration qui fait des `SET`, tourne dans une tâche planifiée, que votre agent lance aussi à la demande. La tâche reçoit l'adresse directe de la base dans `DB_MAIN_DIRECT_URL`.

## Prochaines étapes

- [Réserver votre API aux personnes de votre entreprise](/fr/guides/outil-interne-compte-entreprise/)
- [Ajouter un cache compatible Redis](/fr/guides/cache-redis/)
- [Comparer avec Heroku Postgres](/fr/comparatifs/while-vs-heroku/)

## Sources

1. [node-postgres, se connecter avec une adresse de connexion (connectionString)](https://node-postgres.com/features/connecting), 2026-11-01

## Questions

### Combien coûte une API Node.js avec sa base sur while ?

Avec l'offre Libre, vous ne payez que les ressources, hors taxes : 5 € par mois pour une base S, plus 0,25 € par Gio de disque, et pour l'API, 17 € par vCPU et 8,50 € par Gio de mémoire, par mois, selon sa consommation. Une API qui utilise au plus 0,25 vCPU et 0,5 Gio de mémoire paie au plus 8,50 € par mois, et 13,75 € avec une base S et son disque de 1 Gio.

### Où est hébergée mon API ?

En France, par Nextmap, une entreprise française.

### Mon API s'endort-elle quand personne ne l'appelle ?

Non, en production elle reste éveillée. Avec sleep: 30m dans while.yaml, elle s'endort après 30 minutes sans requête, et la première requête la réveille en quelques secondes.

### Puis-je mettre mon API sur mon propre domaine ?

Oui. Votre agent déclare le domaine, vous ajoutez les deux enregistrements DNS qu'il vous donne, et le certificat HTTPS est obtenu à la première visite.

### Où mettre les clés d'API et les mots de passe de mon API ?

Jamais dans le code. La clé d'une API externe se saisit dans while et s'ajoute à chaque appel : ni votre API ni votre agent ne la voient. Les autres secrets vont au coffre de while.

### Puis-je faire tourner des traitements en fond ?

Oui. Demandez à votre agent un worker, pour un traitement qui tourne sans arrêt, ou une tâche planifiée, pour un travail à heure fixe.

### Je suis sur Heroku ou Render : comment venir ?

Votre agent reprend le code, recopie la base depuis un export (pg_dump) de Heroku ou de Render, restauré par une tâche, et reporte vos variables d'environnement.

### Puis-je utiliser Express, Fastify ou NestJS ?

Oui, tout serveur Node.js qui démarre par un script de son package.json : start, ou start:prod pour NestJS. Express et NestJS ont déjà été mis en ligne en production sur while.

### Puis-je ouvrir ma base dans pgAdmin ou avec psql ?

Non, la base ne s'ouvre pas depuis votre poste : votre agent la lit et l'exporte pour vous.

### Faut-il régler SSL dans l'adresse de la base ?

Non, l'adresse de DATABASE_URL fonctionne telle quelle, sans sslmode.

### Faut-il écrire un Dockerfile ?

Non. Sans Dockerfile dans votre dépôt, while en génère un pour votre API.
