Aller au contenu

(04) Systèmes / Étude de cas

yourFinance

Les soldes sont garantis par la base de données.

yourFinance est une application de finances personnelles multi-utilisateur : une API en Rust, PostgreSQL et un seul client pour iOS, Android, le web et le bureau. Le code est privé ; cette page montre comment elle est construite et pourquoi.

Début
Juillet 2025
Version
1.2.0, octobre 2026
Équipe
Deux développeurs
Code
Privé

Rust · Axum · SQLx · PostgreSQL 18 · Expo · React Native · Tauri · Docker

Le problème

Des données de finances personnelles ne servent que si l'on peut se fier aux soldes. L'application est utilisée par plusieurs personnes sur plusieurs appareils, et une erreur dans un client ou dans un handler ne doit pas pouvoir laisser un compte avec un mauvais montant.

Elle doit aussi gérer plusieurs devises, reprendre tout l'historique d'une autre application (Money Manager) et afficher des statistiques qui ne sont jamais périmées.

Contraintes

  • L'API n'écrit jamais un solde : chaque variation est un mouvement, y compris l'ajustement.
  • Chaque ligne personnelle appartient à un utilisateur, et PostgreSQL répète la règle avec la row-level security sur chaque connexion du pool.
  • Un seul code pour iOS, Android et le web ; l'application de bureau est l'export web dans une coque Tauri.
  • Un changement du schéma ou de l'API doit casser le build, pas l'application en service : le SQL est vérifié à la compilation et les types du client sont générés à partir du document OpenAPI.

Architecture

Trois niveaux : le client se limite à présenter, l'API authentifie, valide et agrège, la base de données est la source de vérité. L'API est un workspace Cargo de crates en couches : chacun ne dépend que de ceux du dessous, et la CI vérifie que le domaine reste sans E/S.

  1. yourf-api

    HTTP : routes fines, authentification, traduction des erreurs, OpenAPI.

    yourf-worker

    Tâches de fond : notifications push, récapitulatif des alertes, mouvements récurrents, rapprochement des soldes.

  2. yourf-runtime

    Ce que les deux binaires partagent : configuration, télémétrie, cycle de vie.

  3. yourf-db

    Dépôts SQLx, périmètre de la row-level security, écritures dans une seule transaction.

    yourf-import

    Lecteurs des fichiers d'autres applications vers un format neutre, sans base de données.

  4. yourf-domain

    Modèles, contrats et règles métier. Aucune E/S.

Deux binaires, une seule image : l'API et le worker se déploient et montent en charge séparément.

Une requête, de bout en bout

La création d'un mouvement :

  1. 01Client

    Le formulaire valide le brouillon et l'envoie avec le jeton.

  2. 02API

    Elle authentifie le jeton, charge l'utilisateur, valide le corps et insère le mouvement avec ses répartitions par compte et par catégorie dans une seule transaction.

  3. 03Base de données

    Des triggers différés vérifient que les répartitions tombent juste et que comptes, catégories et étiquettes appartiennent à l'utilisateur, puis mettent à jour les soldes. Une violation annule tout et devient un 400 avec un code de règle stable.

  4. 04Client

    En cas de succès, les listes, les totaux et le tableau de bord se rechargent.

Choix et compromis

  1. 01

    L'intégrité vit dans la base de données

    Les soldes, la propriété des données et les règles sur les catégories sont garantis par des triggers. Cela veut dire écrire de la logique en SQL plutôt qu'en Rust ; en échange, aucun client et aucun handler ne peut corrompre les données.

  2. 02

    Des soldes vérifiables, pas une partie double complète

    Chaque effet sur un solde est une écriture signée, avec une seule définition utilisée à la fois par le trigger qui écrit les soldes et par la tâche qui les rapproche. Une partie double complète ne vaudrait la réécriture que si une fonction avait besoin d'un bilan.

  3. 03

    Un virement est un mouvement avec deux montants

    Ce qui a quitté le compte d'origine et ce qui est arrivé à destination. La différence couvre aussi bien un change qu'une commission, qui n'apparaît donc pas comme une dépense dans les statistiques.

  4. 04

    Pas de file de tâches

    Le worker prend les lignes à traiter avec FOR UPDATE SKIP LOCKED et la file des notifications push est réveillée par LISTEN/NOTIFY. Chaque passage est idempotent : l'exécuter deux fois, ou sur plusieurs réplicas, donne le même résultat.

  5. 05

    Des statistiques calculées à chaque requête

    Le tableau de bord et les statistiques agrègent les mouvements en SQL à chaque fois : pas d'agrégats précalculés ni de cache, donc les chiffres ne sont jamais périmés. Le prix à payer : les requêtes doivent être rapides par elles-mêmes.

Mesures

Le profilage des requêtes analytiques en a montré deux dont le coût suivait tout l'historique au lieu de la période choisie. Avec le plan générique d'une requête préparée, le planificateur choisissait une boucle imbriquée qui relançait une jointure pour chaque mouvement. Les index n'y étaient pour rien : la correction a consisté à réécrire la vue pour que chaque branche parte du mouvement.

Profil de démonstration, un an de données, plans génériques, mesuré avec EXPLAIN ANALYZE sous le rôle de l'application.
RequêteAvantAprès
Flux quotidiens (tendance des statistiques)daily_flows64.5 ms1.9 ms
Dépenses essentielles (résumé du tableau de bord)essential_expenses48.0 ms1.5 ms

L'application

Tableau de bord de yourFinance sur ordinateur : patrimoine net, FIRE number, taux d'épargne, fonds d'urgence et courbe du patrimoine net sur douze mois.
Tableau de bord : six indicateurs, patrimoine net sur douze mois, répartition des actifs. Données de démonstration.
Écran Statistiques : revenus, dépenses, net et taux d'épargne des douze derniers mois, avec un histogramme mensuel.
Statistiques : revenus et dépenses par mois, avec filtres et répartition par catégorie, compte ou étiquette. Données de démonstration.
Liste des mouvements sur téléphone : totaux des revenus et des dépenses, puis une carte par mouvement.
Le même code sur téléphone : la liste des mouvements. Données de démonstration.

La suite

  • Une date d'échéance sur les comptes, avec un avertissement avant qu'elle n'arrive.
  • L'amortissement : un coût réparti sur plusieurs mois dans les statistiques, alors que le solde reste en trésorerie.
  • Un assistant qui répond aux questions sur les statistiques et les comptes avec des outils en lecture seule : le modèle choisit l'outil, chaque chiffre est calculé par le backend.

Code et démonstration

Le dépôt est privé. Sur demande, je montre le code et l'application en fonctionnement.

Me contacterRetour à Systèmes