Two HN launches captured the shape of the category. Dropbase launched in 2023-12 with 207 points and 114 comments — "build internal web apps with just Python." Creo (YC W24) followed with 97 points and 106 comments — "build internal tools with NextJS and AI." Both threads degenerated into the same argument: when is an internal-tools builder the right answer, and when should the team just write a Rails app?

The argument is real and the answer is concrete. This article is the decision framework.

What an internal-tools builder actually is

An internal-tools builder is a thin shell over your database: connect to Postgres or your API, drop in a table view, attach a form, give some teammates login. Retool, Appsmith, Tooljet, Dropbase, AppElixir, and a dozen others sit in this category with different surface choices. The common thread: the builder owns the auth, the UI primitives, and the deployment; you own the data and the logic.

What this gets you cheaply:

Where the builder fits

The clean cases:

  1. Narrow CRUD over a few tables. Customer admin, refund processor, content moderator. Two to five tables, two to five operations each.
  2. Ten to fifty internal users. Below ten and you might as well share a Notion. Above fifty and you start needing platform features the builder does not have.
  3. Workflows you expect to change. An internal tool that will be rewritten in six months when the team learns what they actually need is cheaper to iterate in a builder than to refactor in Rails.
  4. Teams without an engineer dedicated to internal tooling. If the tool will be maintained by a PM or ops lead with occasional engineering help, the builder is the natural fit.

Where the builder breaks

The breaking points are concrete:

The hidden cost of going to Rails too early

This is the more common error. A small team needs an internal tool, has a Rails-shop instinct, and spends two weeks scaffolding what a builder would have stood up in a day. The Rails app ships, accrues two thousand lines of code, and is maintained by whoever drew the short straw at standup. When that person leaves, the tool rots.

The Dropbase HN thread (114 comments) is full of this exact recognition: engineers who realized in hindsight they had built a Rails app to solve a 10-table CRUD problem because "we're a Rails shop" was the default. The cost was not just the two weeks. The cost was the maintenance debt for the next two years.

The case for Rails (or Django, or Phoenix, or...)

The honest cases for a hand-rolled web framework:

  1. The tool is becoming a product. External customers, multi-tenancy, custom workflows, sales-led pricing. At that point you are no longer building an internal tool; you are building a SaaS, and the SaaS deserves a real framework.
  2. You have permanent engineering ownership. One or more engineers whose job includes the internal tool, who will refactor as the team learns. Without that, Rails will outlive its understanding.
  3. The domain logic is genuinely complex. Workflow engines, state machines, scheduling, multi-step async work. Rails models, ActiveJob, callbacks fit this; builder primitives do not.
  4. You need authentication beyond what builders offer. Devise + custom strategies, OAuth provider, JWT-issuing service, SCIM provisioning. None of this fits cleanly in a builder.

The decision tree

Three questions in order:

  1. Will this be maintained by an engineer in perpetuity? If no, the builder is almost certainly right.
  2. Does the workflow need primitives beyond CRUD + simple integrations? If no, the builder is right.
  3. Is the user base homogeneous (one tenant, internal team) or is it becoming a product? If internal-only, builder. If becoming a product, Rails or equivalent.

If you answered "builder" to all three, build in the builder. If you answered "Rails" to all three, build in Rails. Most real teams are mixed, and the right answer is a builder for the internal-tool surface plus a real framework for the parts of the system that have outgrown it.

The composition pattern

The most successful production setups we see are not "builder or Rails" but "builder and Rails": a builder hosts the team-facing internal tool, a Rails or Phoenix or Go service owns the part of the system the builder cannot do (real-time multiplayer, complex workflows, external customer auth). The builder calls the service over REST or webhooks. Each tool does what it is good at.

Examples we have seen in practice: a builder runs the support team's case-management UI, while a Rails app owns the customer-facing portal. Or a builder hosts the ops team's admin panel, while a Phoenix service handles the multiplayer game state. Or a builder is the back-office for content, while a Hugo or Astro stack renders the public site.

The composition reduces both tools' surface to what they handle well. You stop trying to force the builder into being a backend, and you stop trying to force Rails into being a no-code form maker.

What I would actually do

  1. Default to the builder. The cost of being wrong-and-having-to-rewrite is one day of work. The cost of building Rails-when-builder-would-do is two years of maintenance.
  2. Reach for Rails when you hit a concrete wall. Auth complexity, workflow depth, multi-tenancy, performance — one of these is your trigger.
  3. Don't refactor the whole thing. The internal-team-facing surface can stay in the builder. The customer-facing or workflow-heavy surface moves to the framework.
  4. Document the composition. Two systems, one team — the boundaries matter. Write down what each owns.

The honest framing: the internal-tools builder vs Rails decision is not about "code" vs "no-code." It is about who maintains the thing, how much workflow depth it has, and whether it stays internal. Get those three answers right and the tool falls out.