Skip to content

ADR 001: Build FastAPI Alongside Flask

Status: Accepted
Context: SeedTrust backend architecture


Context

The original SeedTrust backend is a Flask monolith (seedtrust_flask). By 2022–2023, the platform needed to support a mobile Progressive Web App and integrate with the Huntington Bank API — requirements that exposed several limitations of the Flask codebase:

  • Flask uses synchronous SQLAlchemy. Async I/O is impractical to retrofit into a mature synchronous codebase.
  • Flask is tightly coupled to Jinja2 server-rendered templates. It was not designed to serve as a pure JSON API. Adding a clean REST API layer would require significant restructuring.
  • The Flask codebase is large and complex. reports.py alone is ~2,500 lines of raw SQL. The cron server (app_cron.py) is 66KB of unstructured procedural code. Introducing async patterns into this codebase carried high regression risk.
  • Flask uses bcrypt session-cookie auth. The mobile PWA required stateless JWT auth that is portable across devices and compatible with standard OAuth flows.

The alternative was to extend Flask with Flask-RESTX or similar, add JWT support via Flask-JWT-Extended, and migrate to async patterns incrementally. This was considered but rejected due to the scope of change and the risk of destabilizing a system actively processing financial transactions.


Decision

Build a new FastAPI service (seedtrustapi) that runs alongside Flask, sharing the same MySQL database.

  • FastAPI handles: All new features, the mobile PWA API surface, Huntington Bank integration, async background jobs (Huey), and push notifications.
  • Flask handles: The existing desktop admin UI, NACHA batch generation, report generation, legacy email notifications, and critical bug fixes.
  • Both services share: The MySQL database, the seedtrust_schema package (shared SQLAlchemy column definitions), and the same user records and business data.

All new features are built in FastAPI. Flask receives only critical bug fixes.


Consequences

Positive:

  • FastAPI async support enables efficient handling of Huntington API calls, background jobs, and SSE streaming without blocking
  • Clean separation: FastAPI modules have a consistent structure (route.py, service.py, models.py per feature)
  • JWT-based auth is portable and stateless — no session affinity required
  • Pydantic validation is enforced at the API boundary
  • OpenAPI documentation is generated automatically

Negative:

  • Dual maintenance burden. Two backends means two deployments, two test suites, two auth systems, and two sources of truth for business logic that hasn’t been migrated yet
  • Feature parity gap. Some Flask features (full RBAC permission system, NACHA generation, report endpoints) do not exist in FastAPI. Developers must know which service owns which feature
  • Shared database, separate ORMs. Both services write to the same tables but use different ORM instances. Schema changes must be compatible with both. Flask uses sync SQLAlchemy; FastAPI uses async SQLAlchemy. Migrations are currently managed separately per service
  • tokenError in sessions. If the FastAPI refresh token expires, the user remains “logged in” in NextAuth but all API calls fail. Automatic sign-out on token expiry is not yet implemented

Current State

FastAPI remains a production support surface for the mobile PWA and integrations it already owns, but it is no longer the active destination for new product ownership. The current long-term plan is to consolidate behavior back into Flask and make seedtrust_flask the single primary application (see ADR 003).

See also: Migration Guide, Authentication & Permissions