AOCyber
Abstract illustration of interconnected infrastructure nodes showing operational complexity

From Fork to Framework, Part 2: The Python and Svelte Rewrite

March 17, 2026

Python and Svelte formed the backbone of the second major rewrite in our journey from a forked AI chat platform to a framework we could finally call our own. On December 16, 2025 — four days after we shut down active development on our LibreChat and LiteLLM forks — we opened a blank repository and started writing what we internally called "v2." The plan was simple to state and hard to execute: rebuild everything we had learned during the fork period as a clean-room implementation, free of anyone else's architectural decisions. Over the next eight weeks, through February 13, 2026, that plan produced 242 commits, a working product, and a hard-won understanding of exactly what a Python and Svelte stack can — and cannot — do for an AI company trying to scale.

Why We Chose Python and Svelte for Our AI Stack

We chose Python and Svelte for complementary reasons, not because either language was trendy. Python gave us direct access to the machine learning ecosystem — nearly every AI library, every embedding model, and every NLP (natural language processing, the branch of AI that helps computers understand human text) toolkit ships Python bindings first. In contrast, Svelte gave us a reactive frontend with less boilerplate than React, a compiler-first architecture that produced smaller bundles, and SvelteKit's file-based routing that made creating new pages almost instant.

In other words, Python handled the brains of our product — the AI logic, embeddings, and data processing — while Svelte handled the face of it. That division of labor is exactly why so many AI startups reach for a Python and Svelte combination: it lets a small team move fast on both the intelligence layer and the interface layer without context-switching between wildly different paradigms. We'll walk through the full stack, the architecture that resulted, and — just as importantly — where this pairing started to show its limits.

Starting From Scratch (Almost)

During those eight weeks, we built a credit-based billing system, a persona engine, web search integration across three providers, a knowledge base with vector embeddings, memory extraction with entity relations, real-time collaboration, OAuth authentication, admin dashboards, and an early demo of family parental controls. Above all, we learned — the hard way — that feature velocity and operational simplicity are not the same thing. You can see the patterns and conventions that came out of this period in our documented code examples, which still reflect a lot of the thinking from this stage.

The Stack: Svelte, FastAPI, and the Python ML Ecosystem

Here is the complete stack, piece by piece, so you can see exactly how a production Python and Svelte application is assembled in practice:

  • Frontend: SvelteKit 2 + Flowbite Svelte Pro + Tailwind CSS 4
  • Backend: FastAPI (Python 3.11+) with async/await
  • ORM: SQLAlchemy 2.0 with SQLModel
  • Database: PostgreSQL 16 with pgvector for embeddings
  • Cache and pub/sub: Redis 7
  • Background tasks: Celery with a Redis broker
  • Real-time: Socket.io (a library that builds on the browser's native WebSocket API)
  • AI providers: LiteLLM (as a library, not a fork)
  • Deployment: DigitalOcean App Platform

The Svelte Half: SvelteKit 2, Flowbite Svelte Pro, Tailwind CSS 4

On the frontend side, Svelte compiles your component code into small, efficient vanilla JavaScript at build time, rather than shipping a large runtime framework to the browser. SvelteKit builds on top of that with file-based routing, meaning a new URL route is often just a new file in the project. Flowbite Svelte Pro added a library of pre-built, commercially licensed components — tables, charts, forms — that accelerated internal tooling considerably. Tailwind CSS 4 kept utility-first styling consistent across the whole frontend.

The Python Half: FastAPI, SQLAlchemy 2.0, and PostgreSQL 16

On the backend, FastAPI gave us automatic OpenAPI documentation and request validation through Pydantic, Python's data-validation library. SQLAlchemy 2.0, paired with the SQLModel convenience layer, handled our database models with an async session, which meant database calls did not block FastAPI's event loop. Specifically, we relied on PostgreSQL 16 with the pgvector extension so our vector embeddings — the numerical representations AI models use to measure meaning — could live in the same database as everything else, instead of a separate vector store.

Supporting Infrastructure: Redis, Celery, and Socket.io

Redis 7 served two separate jobs at once: caching frequent reads and acting as the message broker for Celery, our background task queue. Celery, in turn, handled anything too slow or too CPU-intensive to run inside a normal web request — embedding generation, memory extraction, and credit reconciliation. Socket.io ran as its own process, communicating with FastAPI through Redis pub/sub to push real-time events to the browser. As you'll see shortly, this list of supporting services is where the real operational cost of the stack started to show up.

How the Architecture Fits Together

graph TB subgraph Frontend SK["SvelteKit 2, Flowbite Svelte Pro, Tailwind CSS 4"] end subgraph Backend FA["FastAPI, Python 3.11+ async"] SA["SQLAlchemy 2.0 + SQLModel"] LITE["LiteLLM, Provider Abstraction"] end subgraph Infrastructure PG[(PostgreSQL 16 + pgvector)] REDIS[(Redis 7, Cache + Pub/Sub)] CEL["Celery Workers, Background Tasks"] SIO["Socket.io, WebSocket Server"] end SK -->|REST + WebSocket| FA SK -->|Real-time events| SIO FA --> SA SA --> PG FA --> LITE FA --> REDIS FA --> SIO CEL --> REDIS CEL --> PG LITE -->|OpenAI, Anthropic, Azure, Bedrock| PROVIDERS["AI Providers"] style SK fill:#141414,stroke:#d4a853,color:#fff style FA fill:#141414,stroke:#d4a853,color:#fff style SA fill:#141414,stroke:#d4a853,color:#fff style LITE fill:#141414,stroke:#d4a853,color:#fff style PG fill:#141414,stroke:#d4a853,color:#fff style REDIS fill:#141414,stroke:#d4a853,color:#fff style CEL fill:#141414,stroke:#d4a853,color:#fff style SIO fill:#141414,stroke:#d4a853,color:#fff style PROVIDERS fill:#141414,stroke:#d4a853,color:#fff

Compared to the fork-based v1, this architecture had one clear advantage: we owned every line of application code. There were no upstream merges to dread, no rebranding to maintain, and no foreign opinions about database schema design buried in our models. The application layer was entirely ours.

However, the infrastructure layer had grown considerably. Where v1 relied on MongoDB, PostgreSQL, and Redis, v2 required PostgreSQL with pgvector, Redis for both caching and Celery's message broker, Celery workers, and a dedicated Socket.io server. That's four infrastructure dependencies, each with its own failure modes, scaling characteristics, and operational overhead.


What We Built With This Stack

The Credit System

We replaced flat-rate Stripe subscription tiers with a credit-based billing model. Users purchased credits, and each AI interaction deducted a calculated cost based on the model used, the token count, and the operation type. As a result, this was far more flexible than flat-rate subscriptions — a user who sent ten messages a month paid less than a power user who sent ten thousand — and it mapped cleanly onto our own costs, since AI providers charge per token.

SQLModel made the credit ledger straightforward: a CreditTransaction model with debit and credit entries, linked to users and conversations. In particular, the async SQLAlchemy 2.0 session gave us non-blocking database access inside FastAPI's event loop, which mattered when a single chat response involved several database writes at once: deducting credits, storing the message, updating conversation metadata, and logging the AI provider's response.

Personas let users configure system prompts, model preferences, temperature settings, and tool access as reusable profiles. For example, a "Research Analyst" persona might use Claude with web search enabled and a low temperature, while a "Creative Writer" persona might use GPT-4 with a high temperature and no tools at all.

Web search itself was integrated through three providers: Serper, Exa, and Tavily. Since each returned different result formats, we built a normalization layer that produced a consistent SearchResult schema regardless of provider. The AI model received search results as structured context, and the frontend rendered source citations inline — a small detail that made a noticeable difference in user trust.

Knowledge Base and Memory

The knowledge base used pgvector to store document embeddings directly inside PostgreSQL. Users could upload documents, which were chunked, embedded using OpenAI's embedding models via LiteLLM, and stored as vectors alongside their source text. During conversation, relevant chunks were retrieved through cosine similarity (a mathematical way of measuring how closely two pieces of text relate in meaning) and injected into the model's context window.

Memory extraction went further still. After each conversation, a background Celery task analyzed the exchange and extracted entity-relation triples. For instance, "the user's daughter is named Sarah" became a structured relation (user → daughter → Sarah) stored in a dedicated memory table. These relations were retrieved in future conversations to give the AI persistent knowledge about the user — a feature that proved especially compelling in our family safety demos.

Real-Time Collaboration and Admin

Socket.io powered our real-time features: streaming AI responses token-by-token to the frontend, live presence indicators showing which team members were online, and collaborative conversation viewing. The Socket.io server ran as a separate process, communicating with FastAPI through Redis pub/sub — similar in spirit to the browser's native WebSocket API, but with reconnection handling built in.

The admin dashboard, built with Flowbite Svelte Pro's component library, provided user management, credit balance oversight, usage analytics, and system health monitoring. Flowbite's pre-built tables, charts, and form components accelerated this work considerably — in fact, the admin UI was functional within a single week.

AODex family safety chat preview from the Python and Svelte iteration
The family safety chat preview from our Python and Svelte iteration, showing parental monitoring controls and child-safe personas.

The Supabase Detour

We initially used Supabase for authentication and real-time subscriptions, drawn in by its managed PostgreSQL, built-in auth, and row-level security. A related side experiment, eden-app-framework — a SvelteKit + Supabase + FastAPI + Tauri v2 concept for a desktop app — received exactly one commit on December 25 before we recognized it was a distraction. We eventually revisited those Eden ideas properly, which you can read about in Part 6, on ConnectRPC and the Eden libraries.

Supabase itself became a problem for a different reason: we were running FastAPI with its own auth system alongside Supabase's auth, which created two sources of truth for user identity. JWT tokens from Supabase needed to be validated inside FastAPI middleware, yet our credit system, admin roles, and team memberships lived in FastAPI's own database. That impedance mismatch produced bugs that were subtle and genuinely time-consuming to diagnose.

Consequently, we migrated to FastAPI-native authentication — OAuth providers wired directly into our SQLAlchemy user model — and the entire auth surface area simplified overnight. Supabase remains an excellent product for teams that build on top of it from day one; it is a less natural fit once your backend already has its own strong opinions about data and identity.

Python and Svelte: What We Gained vs. What It Cost Us

To make this concrete rather than abstract, here is a direct, line-by-line breakdown of what the Python and Svelte combination gave us, and what it quietly cost us in return:

Advantage Cost
Direct access to the ML/AI ecosystem — every library is Python-firstThe GIL (Global Interpreter Lock) limits true concurrency; async helps I/O but not CPU-bound work
FastAPI's automatic OpenAPI docs and Pydantic validationPython's runtime type system means errors surface at runtime, not compile time
SvelteKit's compiler-first approach produces small, fast bundlesSvelte's ecosystem is smaller than React's; fewer off-the-shelf components
Flowbite Svelte Pro accelerated admin UI developmentCommercial component library created a licensing dependency
SQLAlchemy 2.0 async is mature and well-documentedSQLModel's convenience layer occasionally fights SQLAlchemy's more advanced features
pgvector keeps embeddings in PostgreSQL — no separate vector databaseVector search performance degrades at scale compared to purpose-built solutions
Rapid prototyping — 242 commits in 8 weeks with a small teamFour infrastructure dependencies (PostgreSQL, Redis, Celery, Socket.io) multiply operational surface area
LiteLLM as a library gave us provider abstraction without the fork taxStill a Python dependency with its own release cadence and breaking changes
Tailwind CSS 4 utility classes kept styling consistentTailwind + Flowbite + SvelteKit + custom theme = four layers of styling abstraction
DigitalOcean App Platform simplified initial deploymentApp Platform's constraints became visible once we needed WebSocket support, background workers, and custom networking

The Operational Complexity Problem

Feature velocity was genuinely excellent during this period. SvelteKit's file-based routing meant a new page was simply a new file. FastAPI's dependency injection made adding authenticated, validated endpoints almost mechanical. SQLModel reduced ORM boilerplate significantly. In short, the team was shipping product features every single day.

Yet each feature added operational weight. The credit system needed Celery tasks to reconcile balances. Memory extraction needed Celery tasks to run after every conversation. Web search needed Redis caching to avoid redundant API calls. Real-time collaboration needed Socket.io, which needed Redis pub/sub, which in turn needed careful connection management to avoid memory leaks. This is precisely where a documented development workflow became essential for keeping a growing process count manageable.

By late January 2026, our local development environment required seven separate processes: PostgreSQL, Redis, a Celery worker, a Celery beat scheduler, the FastAPI server, the Socket.io server, and the SvelteKit dev server. On DigitalOcean App Platform, this translated into multiple services, each with its own scaling rules, health checks, and log streams.

The infrastructure was not unmanageable — plenty of teams run far more complex stacks in production every day. That said, for a small team still finding its market, the ratio of infrastructure management to feature development was trending in the wrong direction. Every hour spent debugging a Celery task that silently failed because Redis hit its connection limit was an hour not spent on the product itself.

Python's Concurrency Story

FastAPI's async/await model handled I/O-bound work well. Waiting for AI provider responses, database queries, and Redis operations all yielded cleanly to the event loop. However, Python's Global Interpreter Lock (GIL) — the mechanism that allows only one thread to execute Python bytecode at a time — meant CPU-bound work such as embedding generation, PII detection with Presidio, and entity extraction from conversation text either blocked the event loop or required offloading to Celery.

Celery is a proven solution for background task processing; nevertheless, it is also a distributed system with its own failure modes. Tasks can be lost if the broker restarts, retry logic needs careful configuration, and monitoring requires additional tooling such as Flower or custom health checks. For a product that needed to process every conversation in near-real-time, the Celery dependency started to feel increasingly heavy.

The Frontend Question

SvelteKit 2 was genuinely a pleasure to develop with. The compiler catches entire classes of bugs that React only surfaces at runtime. Reactivity is built into the language itself rather than bolted on through hooks, and server-side rendering with hydration works out of the box.

That said, our product roadmap included native mobile apps and, eventually, a desktop client. SvelteKit produces web applications. While frameworks like Capacitor or Tauri — hence the eden-app-framework experiment mentioned above — can wrap web apps in native shells, the result is a web view that looks and feels like a web view. Users notice this. Our family safety product needed to feel genuinely native on iOS and Android, because parental controls that feel like a website simply don't inspire confidence.

Flowbite Svelte Pro, while high-quality, compounded this concern further. It is a web component library, and its components do not translate to native mobile at all. Choosing it for our admin dashboard was fine; building our entire product UI on it would have meant rebuilding every component the moment we moved to a cross-platform framework.

Is Python and Svelte the Right Choice for AI Products?

In our experience, Python and Svelte make an excellent stack under specific conditions, and a poor one under others. Specifically, this pairing works well when:

  • Your product is primarily a web application, with no near-term need for native mobile or desktop distribution.
  • Your team is small, and you value Python's enormous AI/ML library ecosystem more than raw runtime performance.
  • Your workload is I/O-bound — mostly waiting on network calls to AI providers, databases, and third-party APIs — rather than CPU-bound.
  • You can tolerate, and have the team to maintain, several supporting services (Redis, Celery, a vector-capable database).

On the other hand, Python and Svelte becomes a weaker fit once your roadmap demands native mobile apps, heavy CPU-bound processing at scale, or a single codebase that targets web, mobile, and desktop simultaneously. In our case, it was precisely this second scenario that forced our hand.

Comparing Svelte and Python to Other Tech Stacks

Because so many teams ask us how a Python and Svelte stack stacks up against alternatives, here is an honest comparison based on what we actually experienced building production AI features on it:

Stack Best For Weak Point
Python + Svelte (FastAPI + SvelteKit)AI-heavy web apps, small teams, rapid prototypingNo native mobile/desktop path; GIL limits CPU parallelism
Python + ReactLarge component ecosystems, enterprise hiring poolsMore boilerplate; larger bundle sizes than Svelte
Node.js + SvelteFull-stack JavaScript teams, shared types front to backWeaker native AI/ML library support than Python
Ruby on Rails (monolith)Convention-driven speed, fewer moving infrastructure piecesThinner AI ecosystem; still web-only by default

We actually evaluated Rails seriously as our next step — that story, including why it nearly won, is covered in Part 3.

The Decision: What This Rewrite Taught Us

By mid-February 2026, the Python and Svelte rewrite had proven two things clearly:

  1. We knew what our product was. The credit system, personas, web search, knowledge base, memory, and real-time collaboration were no longer experiments. They were the product. The fork period had identified the features; the rewrite validated them in production.
  2. We knew what our stack needed to be. We needed a backend language with real concurrency — not async-over-GIL, but true parallel execution for CPU-bound AI workloads. We needed a frontend framework that compiled to native mobile, native desktop, and web from a single codebase. And we needed to own our component library so our UI was never coupled to a commercial dependency.

The Python and Svelte rewrite was not a failure. On the contrary, it was the iteration that clarified our requirements with enough specificity to make the right long-term choice. Two hundred and forty-two commits in eight weeks is not wasted work — it is a thorough, production-tested requirements document. That clarity is ultimately what pushed us toward Flutter for our frontend, a decision we detail fully in Part 5, where Flutter won.

What came next was an evaluation of the frameworks that could meet those requirements. One of them nearly won. That is Part 3.

Frequently Asked Questions About Python and Svelte

What is the Python and Svelte stack used for?

A Python and Svelte stack pairs a Python backend — typically FastAPI or Django — with a Svelte or SvelteKit frontend. It's commonly used for AI products, SaaS dashboards, and data-heavy web applications, because Python handles the machine learning and data layer while Svelte delivers a fast, reactive interface.

Why choose Python and Svelte instead of Node.js or Ruby?

Python wins when your product leans heavily on AI/ML libraries, since nearly every model provider and embedding library ships Python support first. Svelte wins on the frontend by compiling away framework overhead, producing smaller bundles than comparable React or Vue apps. Together, they let a small team move quickly on both layers at once.

What are the main drawbacks of a Python and Svelte stack?

The biggest drawback is Python's Global Interpreter Lock, which limits true CPU-bound parallelism and often pushes teams toward background task queues like Celery. On the frontend side, Svelte's smaller ecosystem means fewer ready-made components than React, and neither half of the stack produces a native mobile or desktop app out of the box.

Can Python and Svelte support real-time AI chat applications?

Yes. FastAPI's async/await model handles concurrent I/O well, and adding Socket.io alongside Redis pub/sub enables real-time, token-by-token streaming of AI responses. This combination powered our own real-time collaboration and live chat features throughout the rewrite described in this article.

Is Python and Svelte a good choice for mobile and desktop apps?

Not directly. SvelteKit produces web applications, and while tools like Capacitor or Tauri can wrap that output in a native shell, the result still looks and feels like a web view rather than a true native app. If native mobile and desktop are core requirements, a cross-platform framework built for that purpose is usually a better fit.

What did you ultimately replace the Python and Svelte stack with?

After validating our product requirements with Python and Svelte, we moved our frontend to Flutter for true cross-platform native support, and we explored Rails along the way before settling on our final architecture. Those decisions are covered in Part 3 and Part 5 of this series.


Final Thoughts on Python and Svelte

In the end, Python and Svelte gave us exactly what we needed at that stage of the company: fast access to the AI ecosystem, a reactive frontend with minimal boilerplate, and the ability to ship 242 commits of real product in eight weeks. At the same time, the growing pile of supporting infrastructure — Redis, Celery, Socket.io, four services instead of one — made it clear that this stack was a bridge, not a destination, for a product that needed native mobile apps and true CPU parallelism. If you're evaluating Python and Svelte for your own AI product, treat it the way we did: as an excellent way to prove out your features quickly, while staying honest about where its limits will eventually show up.

Add to Preferred Sources
blog author avatar

Justin Donnaruma

Justin Donnaruma is the founder and Chief Innovation Officer of AOCyber, where he sets the technical direction for a product line built on one constraint: the customer pays, so the customer is never the product. He founded Don't Panic Consulting in 2016 — a managed service provider working with Fortune 500 companies, hedge funds and national brands, with zero customer churn across five years of operations — and founded AOCyber in 2025 to build AI-native, privacy-first platforms. He writes here about AI governance, the economics of "free" AI, and what actually holds up when a model reaches production.

Back to Blog
AOCyber

You don't have to be the product anymore. Building the next generation of applications.

© 2026 AOCyber. All rights reserved.