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:
- A working app in an afternoon
- Auth managed by the platform (invite-by-email, roles, audit log)
- Standard UI components (tables, forms, charts) that you do not maintain
- Deployment that you do not configure
Where the builder fits
The clean cases:
- Narrow CRUD over a few tables. Customer admin, refund processor, content moderator. Two to five tables, two to five operations each.
- 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.
- 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.
- 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:
- Auth that goes beyond invite-by-email. The builder ships team-style auth: roles, invitations, sharing. The moment you need anonymous-then-upgrade, SSO with custom IdP, per-record permissions based on dynamic state, or auth tokens for non-human callers, you are working against the builder rather than with it.
- Multi-tenant data isolation. Most builders assume a single tenant. If your internal tool needs to serve customers (i.e., it is becoming an external product), multi-tenancy is rarely a feature you can bolt on.
- Complex domain logic. Three forms calling stored procedures: fine. A fifteen-step workflow with state machines, retries, side effects, and idempotency: the builder's logic primitives will not stretch.
- Integrations beyond REST. Builders connect to databases and HTTP APIs. If you need WebSockets, gRPC, message queues, or filesystem operations, you are at the builder's wall.
- Performance at scale. Builders are fine for tens of concurrent users. They are not fine for thousands. The platform owns the rendering and the request lifecycle; you do not have the optimization knobs you would have in Rails.
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:
- 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.
- 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.
- 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.
- 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:
- Will this be maintained by an engineer in perpetuity? If no, the builder is almost certainly right.
- Does the workflow need primitives beyond CRUD + simple integrations? If no, the builder is right.
- 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
- 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.
- Reach for Rails when you hit a concrete wall. Auth complexity, workflow depth, multi-tenancy, performance — one of these is your trigger.
- 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.
- 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.