Zum Inhalt springen

(04) Systeme / Fallstudie

yourFinance

Die Salden garantiert die Datenbank.

yourFinance ist eine mehrbenutzerfähige App für persönliche Finanzen: eine Rust-API, PostgreSQL und ein einziger Client für iOS, Android, Web und Desktop. Der Code ist privat; diese Seite zeigt, wie sie gebaut ist und warum.

Beginn
Juli 2025
Version
1.2.0, Oktober 2026
Team
Zwei Entwickler
Code
Privat

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

Das Problem

Persönliche Finanzdaten nützen nur, wenn man den Salden trauen kann. Mehrere Personen nutzen die App auf mehreren Geräten, und ein Fehler in einem Client oder in einem Handler darf kein Konto mit einem falschen Betrag zurücklassen können.

Sie muss außerdem mehrere Währungen verarbeiten, die gesamte Historie einer anderen App (Money Manager) übernehmen und Statistiken zeigen, die nie veraltet sind.

Rahmenbedingungen

  • Die API schreibt nie einen Saldo: Jede Änderung ist eine Buchung, auch die Korrektur.
  • Jede persönliche Zeile gehört einem Benutzer, und PostgreSQL wiederholt die Regel mit Row-Level Security auf jeder Verbindung des Pools.
  • Ein Code für iOS, Android und Web; die Desktop-App ist der Web-Export in einer Tauri-Hülle.
  • Eine Änderung am Schema oder an der API muss den Build brechen, nicht die laufende App: SQL wird beim Kompilieren geprüft, und die Typen des Clients werden aus dem OpenAPI-Dokument erzeugt.

Architektur

Drei Ebenen: Der Client stellt nur dar, die API authentifiziert, validiert und aggregiert, die Datenbank ist die Quelle der Wahrheit. Die API ist ein Cargo-Workspace aus geschichteten Crates: Jedes hängt nur von den darunterliegenden ab, und die CI prüft, dass die Domäne frei von I/O bleibt.

  1. yourf-api

    HTTP: schlanke Routen, Authentifizierung, Fehlerabbildung, OpenAPI.

    yourf-worker

    Hintergrundjobs: Push-Benachrichtigungen, Zusammenfassung der Warnungen, wiederkehrende Buchungen, Abgleich der Salden.

  2. yourf-runtime

    Was beide Binaries teilen: Konfiguration, Telemetrie, Lebenszyklus.

  3. yourf-db

    SQLx-Repositories, Geltungsbereich der Row-Level Security, Schreibvorgänge in einer Transaktion.

    yourf-import

    Leser für Dateien anderer Apps in ein neutrales Format, ohne Datenbank.

  4. yourf-domain

    Modelle, Verträge und Geschäftsregeln. Kein I/O.

Zwei Binaries, ein Image: API und Worker werden getrennt ausgerollt und skaliert.

Eine Anfrage, von Anfang bis Ende

Das Anlegen einer Buchung:

  1. 01Client

    Das Formular prüft den Entwurf und sendet ihn mit dem Token.

  2. 02API

    Sie authentifiziert das Token, lädt den Benutzer, prüft den Inhalt und fügt die Buchung mit ihren Aufteilungen nach Konto und Kategorie in einer Transaktion ein.

  3. 03Datenbank

    Verzögerte Trigger prüfen, dass die Aufteilungen aufgehen und dass Konten, Kategorien und Tags dem Benutzer gehören, und aktualisieren dann die Salden. Ein Verstoß rollt alles zurück und wird zu einem 400 mit einem stabilen Regelcode.

  4. 04Client

    Bei Erfolg werden Listen, Summen und Dashboard neu geladen.

Entscheidungen und Abwägungen

  1. 01

    Die Integrität liegt in der Datenbank

    Salden, Eigentum an den Daten und Kategorieregeln werden von Triggern durchgesetzt. Das heißt Logik in SQL statt in Rust; dafür kann kein Client und kein Handler die Daten beschädigen.

  2. 02

    Prüfbare Salden statt vollständiger doppelter Buchführung

    Jede Wirkung auf einen Saldo ist eine vorzeichenbehaftete Buchungszeile mit einer einzigen Definition, die sowohl der Trigger nutzt, der die Salden schreibt, als auch der Job, der sie abgleicht. Eine vollständige doppelte Buchführung wäre den Umbau nur wert, wenn eine Funktion eine Bilanz bräuchte.

  3. 03

    Ein Übertrag ist eine Buchung mit zwei Beträgen

    Was das Quellkonto verlassen hat und was am Ziel angekommen ist. Die Differenz deckt einen Währungstausch ebenso ab wie eine Gebühr, die deshalb in den Statistiken nicht als Ausgabe erscheint.

  4. 04

    Keine Job-Warteschlange

    Der Worker holt die fälligen Zeilen mit FOR UPDATE SKIP LOCKED, und die Warteschlange der Push-Benachrichtigungen wird über LISTEN/NOTIFY geweckt. Jeder Durchlauf ist idempotent: Zweimal oder auf mehreren Replikaten ausgeführt, liefert er dasselbe Ergebnis.

  5. 05

    Statistiken bei jeder Anfrage berechnet

    Dashboard und Statistiken aggregieren die Buchungen jedes Mal in SQL: keine vorberechneten Aggregate und kein Cache, also sind die Zahlen nie veraltet. Der Preis: Die Abfragen müssen von sich aus schnell sein.

Messwerte

Das Profiling der Analyseabfragen zeigte zwei, deren Kosten mit der gesamten Historie wuchsen statt mit dem gewählten Zeitraum. Mit dem generischen Plan eines Prepared Statements wählte der Planer einen Nested Loop, der einen Join für jede Buchung erneut ausführte. An den Indizes lag es nicht: Die Korrektur bestand darin, die View so umzuschreiben, dass jeder Zweig bei der Buchung beginnt.

Demoprofil, ein Jahr Daten, generische Pläne, gemessen mit EXPLAIN ANALYZE in der Rolle der Anwendung.
AbfrageVorherNachher
Tägliche Flüsse (Verlauf der Statistiken)daily_flows64.5 ms1.9 ms
Notwendige Ausgaben (Zusammenfassung des Dashboards)essential_expenses48.0 ms1.5 ms

Die App

Dashboard von yourFinance auf dem Desktop: Nettovermögen, FIRE Number, Sparquote, Notgroschen und der Verlauf des Nettovermögens über zwölf Monate.
Dashboard: sechs Kennzahlen, Nettovermögen über zwölf Monate, Vermögensaufteilung. Demodaten.
Statistikansicht: Einnahmen, Ausgaben, Netto und Sparquote der letzten zwölf Monate, mit einem monatlichen Balkendiagramm.
Statistiken: Einnahmen und Ausgaben pro Monat, mit Filtern und Aufteilung nach Kategorie, Konto oder Tag. Demodaten.
Buchungsliste auf dem Telefon: Summen der Einnahmen und Ausgaben, dann eine Karte pro Buchung.
Derselbe Code auf dem Telefon: die Buchungsliste. Demodaten.

Wie es weitergeht

  • Ein Ablaufdatum für Konten, mit einem Hinweis, bevor es erreicht ist.
  • Abschreibung: Kosten, die in den Statistiken über mehrere Monate verteilt werden, während der Saldo kassenbasiert bleibt.
  • Ein Assistent, der Fragen zu Statistiken und Konten mit Nur-Lese-Werkzeugen beantwortet: Das Modell wählt das Werkzeug, jede Zahl berechnet das Backend.

Code und Demo

Das Repository ist privat. Auf Anfrage zeige ich den Code und die laufende App.

Kontakt aufnehmenZurück zu Systeme