sixty

pour les services Node

Quelle fonction, quelle requête, quel déploiement.

Un agent, installé en une commande, mesure chaque fonction asynchrone exportée et chaque requête que fait votre application — et sait quelle fonction a émis quelle requête. Chaque version est comparée à la précédente, donc le constat nomme votre déploiement plutôt que l’heure.

Ce qu’il mesure

Chaque fonction asynchrone exportée
Combien de temps elle a pris, et quelle part de ce temps venait de son propre code plutôt que de quelque chose qu’elle a appelé. « Est-ce mon code qui a ralenti, ou ce que j’ai appelé » est ici un chiffre plutôt qu’un après-midi.
Chaque requête, sur cinq clients
pg, mysql2, postgres.js, le pilote MongoDB et Prisma — trouvés et instrumentés automatiquement, y compris à travers Mongoose et un pool de connexions sous charge. Lignes renvoyées, colonnes, taille de la réponse, et pour MongoDB le nombre d’allers-retours réseau qu’une seule lecture a réellement coûté.
Quelle fonction a émis quelle requête
La partie qui rend le reste digne d’être lu. Une requête est créditée à la fonction au-dessus d’elle, donc un N+1 apparaît sur la fonction qui contient la boucle, et non réparti sur une requête qui a toujours eu l’air correcte.
Ce que la base a fait pour répondre
On demande à Postgres le plan de chaque requête — sans jamais lier un paramètre, donc aucune de vos valeurs n’est impliquée. MySQL est lu à la place depuis performance_schema : lignes examinées par ligne renvoyée, et si un index a été utilisé du tout. Les deux arrivent comme le même constat : ceci lit cette table sans index.
Vos routes HTTP, en entrée et en sortie
Requêtes servies, et temps passé à attendre l’API de quelqu’un d’autre — un tiers lent cesse donc d’être signalé comme votre code qui rame.

Ce qu’il trouve

Chacune de ces choses est comparée à la version précédente : le constat nomme donc le changement plutôt que le jour.

Un N+1 qui n’était pas là à la version précédente

Une fonction qui faisait un appel base par requête en fait maintenant quatorze. Ancré au déploiement, donc il nomme la version qui l’a introduit.

Une requête qui s’est mise à lire toute la table

Les lignes par appel sont passées de 30 à 30 000. Sur une base chaude avec des données de taille staging cela bouge à peine l’horloge — et une semaine plus tard cela met la production à terre.

Une requête qui a cessé d’utiliser son index

Le seul constat ici qui nomme une cause plutôt qu’un symptôme. Il arrive souvent avant que quoi que ce soit ne soit lent : la table est encore assez petite pour qu’un balayage passe, et cela devient une panne des semaines plus tard, quand elle ne l’est plus.

Votre propre code qui ralentit

Temps passé dans la fonction elle-même plutôt que dans ce qu’elle a appelé — séparé, pour que vous ouvriez le bon fichier du premier coup.

Une lecture devenue des centaines d’attentes réseau

MongoDB répond à un curseur par lots. Quand un résultat dépasse un lot, une lecture devient des dizaines ou des centaines d’allers-retours successifs — les documents sont identiques, donc rien d’autre ne bouge dans le système que l’horloge.

Quelque chose désormais appelé dans une boucle

Inchangé par appel — même vitesse, mêmes données — mais appelé des centaines de fois là où il l’était une seule.

Une requête qui ne renvoie plus rien, en silence

Réussie, aucune erreur, aucun appel lent, et revenue vide là où elle revenait avec des lignes. La façon la plus courante dont un service comme celui-ci casse fait baisser les chiffres, pas monter.

Ce qui arrive dans votre fil

Pas un tableau de bord à lire. Une carte par constat, avec les chiffres, la version qui les a changés, et les preuves dont votre agent de code a besoin pour écrire le correctif.

Ce sont les chiffres qu’imprime `pnpm e2e`, sur le clone de ce dépôt de n’importe qui. Il prépare un service, livre une version avec deux vraies régressions, et les détecte — donc rien ici n’est un chiffre que nous avons choisi.

lignesorders.getUserOrders
30 lignes30 000 lignes1000×

Une clause WHERE a disparu lors d’une refonte, donc la fonction récupère toute la table et la filtre en JavaScript. Sur une base chaude, l’horloge a à peine bougé.

depuis la version v2, contre la v1

N+1orders.enrichOrders
1 requête14 requêtes14×

Une requête s’est déplacée dans une boucle. Chacune est rapide, donc aucune requête prise seule n’a l’air fausse — le nombre est la seule chose qui a changé.

depuis la version v2, contre la v1

Comment ça s’installe

Remettez-le à l’agent de code que vous avez déjà ouvert. Il lit le dépôt, détermine si cela veut dire une configuration Next, un plugin Vite ou une commande de démarrage, et le branche — puis corrige ce qui est trouvé, dans la même conversation.

claude mcp add sixty \
  -e SIXTY_API_KEY=sixty_sk_… \
  -e SIXTY_ENDPOINT=https://ingest.sixty.sh \
  -- npx -y @sixty-sh/mcp

# or by hand, in your server entry:
import { init } from '@sixty-sh/node'
init()

L’identifiant de version est récupéré tout seul chez Vercel, Render, Railway, Fly, Heroku ou GitHub Actions. La première comparaison arrive après votre prochain déploiement, parce qu’il n’y a rien à quoi comparer une version isolée.

Ce qu’il ne fait pas

  • MySQL et MongoDB ne remontent aucun arbre de plan. L’EXPLAIN de MySQL a besoin de vraies valeurs de paramètres et l’explain de MongoDB d’un vrai filtre, et cet agent jette les valeurs dès qu’il les voit — pour MySQL la conclusion est donc lue depuis performance_schema, et pour MongoDB il n’y a encore rien.
  • Les générateurs asynchrones sont ignorés par la transformation au build. En envelopper un mesurerait le temps mis avant que l’appelant obtienne un itérateur, ce qui n’est pas le chiffre que quiconque veut.
  • L’agent mesure ce qu’il peut atteindre depuis JavaScript. Le temps passé dans un module natif, ou dans un autre processus, est du temps qu’il ne peut voir que comme de l’attente.

Si vous êtes ici pour l’une de ces raisons

Découvrez ce qu’a fait votre dernier changement.

Essayez !

Vous construisez autre chose ? Voyez services Python, applications Lovable ou applications React Native — ces pages sont différentes, et ce que nous voyons aussi.

Surveillance des performances pour Node, Postgres, MySQL et MongoDB — Sixty