Design¶
Design Goals¶
Paisa favors practical self-hosted usability over distributed-system complexity.
Primary goals:
- Keep setup simple for personal finance users.
- Preserve transparency by building on plain-text ledger journals.
- Provide rich analytics and editing workflows in a browser/desktop UI.
- Keep operational footprint small (single process, SQLite, embedded assets).
Current Design Choices¶
Backend design¶
- Language/runtime: Go for backend services and CLI.
- Web stack: Gin router + JSON APIs.
- Persistence: SQLite via GORM.
- Domain organization: package-per-concern under
internal/.
Trade-off:
- Fast development and portability, but some business logic is tightly coupled to handler flows.
Frontend design¶
- SvelteKit SPA (
ssr = false) with static build output. - Local state via Svelte stores in
src/store.ts. - REST API access through a shared
ajaxhelper insrc/lib/utils.ts.
Trade-off:
- Simple deployment and fast client UX, but auth token management currently relies on browser storage.
Authentication design¶
- Optional user accounts in config (
internal/config/config.go). - API auth middleware validates
X-Authheader for API routes. - Rate limiter slows repeated invalid credentials.
Trade-off:
- Works for personal/self-hosted use, but lacks hardened session semantics expected in hostile networks.
Sync design¶
- Journal sync validates and parses journal files.
- Price/portfolio sync fetches external market data.
- DB is refreshed in place by model upsert logic.
Trade-off:
- Functional and straightforward, but partial-failure handling and transactional consistency can be improved.
Design Principles For Future Changes¶
- Keep web and desktop behavior aligned by reusing backend handlers/services.
- Shift domain orchestration out of route handlers into explicit service boundaries.
- Prefer deterministic, testable pure functions for financial calculations.
- Treat filesystem operations and external scrapers as side-effect boundaries.
- Keep read paths fast and stable; isolate write/sync paths for observability.
Extension Guidelines¶
Adding a new analytics capability¶
- Add domain model/service logic under
internal/first. - Add API route in
internal/server/with clear request/response shape. - Add typed frontend integration in
src/lib/. - Add route/view and store wiring in
src/routes/andsrc/store.tsas needed. - Add regression fixtures/tests when output shape is stable.
Adding a write path¶
- Enforce
readonlybehavior consistently. - Validate request payloads with strict binding.
- Wrap multi-step persistence changes in DB transactions.
- Emit structured logs for auditability.
Adding external data providers¶
- Implement provider behind scraper abstraction.
- Add provider-specific tests with deterministic fixtures.
- Add timeout/retry/backoff policy and failure classification.
- Ensure cache invalidation strategy is explicit.
Non-Goals (Current Scope)¶
- Multi-tenant user isolation.
- Distributed storage and horizontal write scaling.
- Full enterprise IAM/OIDC integration.
Design Debt To Track¶
- Global config mutability and thread-safety concerns.
- Inconsistent API error response contracts.
- Handler-level policy checks repeated across endpoints.
- Limited formal migration/version management for DB schema.