Back to Journal
build-vs-buyno-codefounder-toolingstreamlit-to-react

Build vs Buy vs No-Code: A Decision Framework

A decision framework for early-stage founders built from real scaling choices, not theory. Know when Streamlit breaks before it does.

Tamas Czaban
Developer workspace showing the build vs buy custom software decision process in practice

The number that forces the decision is almost always smaller than you expect.

For us it was twenty. Twenty concurrent users on Streamlit, and Zsombor ran the hosting math and came back with a verdict: rewrite in React or watch the bill eat the product. That number on a spreadsheet is the entire build vs buy vs no-code debate compressed into a single line item. The framework you actually need is not the one you reach for after the pain is acute. It is the one you run before you commit to your first tool choice.

This is that framework, assembled from the decisions we made building VitalRegistry -- a rental CRM for BEMER device distributors -- and the agentic development system we built around it. None of it is theory. All of it has a bill attached.


The Trigger Event

Every build vs buy vs no-code crisis has a trigger. The trigger is not a philosophical question about scalability. It is a concrete number or a specific failure mode that makes the current path obviously untenable.

Recognise the common triggers:

  • A hosting cost calculation that breaks at a specific user count (ours: 20 concurrent users on Streamlit)
  • A design ceiling where the tool cannot render what the product needs to look like
  • A data model that cannot be expressed inside the platform's constraints
  • A workflow step that requires manual intervention every single time

Streamlit's hosting cost would have broken us past twenty concurrent users. That single number is what triggered the React migration. The framework mattered less than having the number. Run the math on your current tool before you need to. Know the ceiling.


The Three Paths

No-code and low-code tools

The right default for unproven demand. Streamlit gave us a working prototype in six weeks: auth, device tracking, client records, and the table views mum needed, all live and in her hands by mid-February. Six weeks from mum asking us at Christmas whether we could build something to a Streamlit prototype she used daily. The first version was not pretty. It was usable, and usable was the only metric that counted.

No-code and low-code belong at the start of the stack when:

  • The domain is new and the data model is still guesses
  • The user base is small enough that the hosting math does not break you
  • Speed to first real user outweighs everything else

The exit criteria are equally clear. Leave when the hosting math breaks. Leave when the design ceiling prevents you from shipping something that looks like a product. Leave when the platform's data model forces compromises that leak into the user experience.

Do not leave early. The Streamlit prototype proved demand before we wrote a line of React.

Buying SaaS

The right choice when the problem is solved and the integration cost is lower than the build cost. For VitalRegistry the SaaS options were general CRM platforms. None of them modelled BEMER device rentals, sub-rentals, subletting, or the contract-generation-and-upload loop the distributors needed. The integration cost to bend a general CRM into the right shape exceeded the cost of building. We built.

Buy SaaS when:

  • The platform models your domain without heavy customisation
  • The vendor's roadmap moves in the direction your users need
  • The per-seat cost stays below the engineering cost of the equivalent feature set

The hidden buy vs build calculus is maintenance, not initial build cost. A SaaS subscription absorbs security patches, infrastructure scaling, and breaking API changes. A custom build assigns all of those to your team permanently. Account for that before choosing build.

Building custom

The right choice after you have proven the problem is real and the existing tools cannot serve it. React gave us what Streamlit could not: a real component library, proper routing, mobile-friendly layouts, contract generation, in-app reminders, and calendar sync. The design system we built during the migration now lives across every CZ Dev product. The CRM replaced spreadsheets so completely that the end of month reconciliation, which used to eat a full day, now runs in minutes.

Build custom when:

  • You have proven demand (real users, specific feedback, willingness to pay)
  • The domain has constraints no off-the-shelf tool models correctly
  • The build produces an artifact that compounds -- a design system, a data model, a deployment pipeline -- that serves future work

Do not build custom to avoid the constraint of the tool. Build custom because the constraint of the tool has become the bottleneck for real users doing real work.


The Decision Matrix

These are the actual decisions from the VitalRegistry build, structured as a repeatable format.

Backend infrastructure

  • Options considered: Roll our own Postgres and Auth stack, build on Supabase, build on Firebase, thin custom Node API on top of any of the above.
  • Chosen: Firebase end to end. Firestore for data, Firebase Auth for login, Firebase Hosting for the frontend.
  • Rationale: Generous free tier for our scope. Google-backed so we are not betting on a startup outliving the project. Firestore and Firebase Auth ship with most of what a CRM needs out of the box. Less code to write is more time to learn the domain.
  • Tradeoff: Locked into Google's data model and pricing curve. The migration off Firestore, if usage scales hard, is the bill we will pay later. We accepted that bet deliberately.

Frontend framework

  • Options considered: Keep iterating in Streamlit, full rewrite in React, hybrid (Streamlit for admin, React for users).
  • Chosen: Full React rewrite.
  • Rationale: Streamlit runs on the server, not the client. Past twenty concurrent users the hosting cost breaks. The rewrite also gave us cover to ship a real design system instead of the fast-and-ugly prototype.
  • Tradeoff: Five months of part-time engineering work and a UI mum had to relearn. She did, without complaint.

AI tooling for the build itself

  • Options considered: Keep using Gemini Pro in browser tabs with manual context paste, run Claude Code against a local Qwen Coder 27B on the RTX 3090 via a custom proxy, buy the $20 Claude subscription.
  • Chosen: $20 Claude subscription for project work, local stack repurposed for the internal RAG knowledge base.
  • Rationale: Qwen Coder 27B explored twenty thousand lines of code in twenty minutes on a request to make a small edit. The model did not trust its own tool-call grammar and compensated by reading everything, repeatedly. The output was unusable. The hosted model stayed coherent on long contexts. The 3090 found its real job indexing our internal knowledge base instead.
  • Tradeoff: A monthly subscription we no longer dodge. The time saved per session paid it back inside a week.

Workflow coordination

  • Options considered: Keep coordinating ad-hoc on Messenger, build a custom orchestrator, adopt GSD and modify it.
  • Chosen: GSD as the backbone, with our own ship phase layered on top.
  • Rationale: Two people and a fleet of agents needed to work the same repo without colliding. Messenger threads of "can I touch this?" were running out of road. GSD already had the issue-to-phase-to-branch loop we needed.
  • Tradeoff: We own the ship phase now. If GSD upstream changes shape, we maintain the diff.

The Non-Obvious Part

The framework above is only useful if you apply it before the crisis, not during it.

Build vs buy gets Googled after the no-code pain is already acute. By the time you are running the math on Streamlit hosting costs, you are already in the middle of the migration decision, not before it. A framework built from real scaling decisions changes the conversation because it gives you the ceiling numbers in advance.

The Streamlit-to-React rewrite took five months of part-time work. If we had known the twenty-user ceiling before we started, we would have designed the data model differently, delayed the no-code phase until we had stronger demand signal, or front-loaded the React rewrite. The ceiling was always there. We just did not run the math until we had to.

Run the math now. For your current tool, calculate:

  1. The hosting cost at 10x your current user count
  2. The design change you cannot make inside the platform
  3. The data relationship the platform's model cannot express
  4. The workflow step that will require manual intervention forever

If you cannot answer all four, you do not know the ceiling. You will find it the same way we did: by hitting it.


A Self-Diagnostic for Your Current Stack

Apply this before you commit to any tool, and again every time your user count doubles.

No-code / low-code is still right if:

  • Demand is unproven or the data model is still changing
  • Your current user count is well below the hosting cost ceiling
  • The platform's design constraints are not visible to your users

Buy SaaS instead of building if:

  • A platform models your domain without heavy customisation
  • The vendor's roadmap moves toward your users' needs
  • Maintenance cost over 24 months is lower than the build cost over 24 months

Build custom if:

  • Real users have given you specific feedback (not polite feedback -- specific feedback)
  • The domain constraints cannot be served by any existing platform
  • The build produces a compound artifact -- design system, data model, pipeline -- that serves more than one product

You are in crisis mode if:

  • You are Googling "build vs buy" because something just broke
  • The migration decision is being driven by a current failure rather than a projected ceiling

The last one is the signal. If the decision is happening in crisis, the framework is already late. The point of running this diagnostic early is to make the migration a planned project, not an emergency rewrite.


We built VitalRegistry to solve one person's spreadsheet problem. The decisions we made -- Streamlit first, React second, Firebase throughout, Claude Code for the build -- were not obviously correct at the start. They became correct by staying close to the ceiling numbers and moving before the ceiling became the floor.

When early users asked whether they would pay for VitalRegistry, the answer was "in a heartbeat." Several said they would happily pay a couple of thousand forint a month for the time it gives back. The demand was real. The tool we built to serve it is real. The framework we used to get there is the one above.

The question for your stack: do you know the number that breaks your current tool?

Working with a tool you've outgrown?

Book a call

Written by

Tamas Czaban