Build a Retool alternative

Build a Retool alternative as a lookup, a dashboard, and an approval queue. The drag-and-drop builder and every data source are the other product.

  • teardown
  • vibe-coding
  • scope

You can build a Retool alternative as a record lookup, an ops dashboard, and an approval queue. The catalog calls Retool that, not a drag-and-drop empire.

You pay $12–$65 a person a month. The card says that price scales with the team. The verdict is “Tools, not the builder”.

Last time I wrote about vibe coding your own IFTTT. That was a regular backlog post. This one is a teardown.

Build a Retool alternative as three screens

The Retool page splits the work into three rows.

The first row is 4 days. Record lookup, ops dashboard, approval queue. That is a search box, a handful of numbers, and a list of pending writes. You can vibe-code this.

The second row is 2 weeks and up. Roles, an immutable audit log, validated write endpoints. Still your tools. A viewer cannot approve. A write names the fields it accepts.

The third row is 3 months and up. Drag-and-drop builder, query IDE, plugin system. Skip that row.

If you tell an agent to “clone Retool”, it aims at the third row. The useful v1 is the first one.

Here is the shape of one request. Nothing else has to exist at 4 days.

const request = {
  id: 'apr-refund-1842',
  kind: 'refund',
  recordId: 'cus-ada',
  amount: 180,
  state: 'pending',
  requestedBy: 'user-marco',
  decidedBy: null,
}

A request, a kind, a record, a state. The write that follows is a typed endpoint. The browser never sends SQL.

The audience on the page is a small team that keeps opening the production database to answer questions. If that is you, three screens are enough. If the company already lives in a canvas of components, keep paying.

The same v1 also replaces Appsmith and Superblocks if what you wanted was a safe admin, not a builder. Airtable is the typed table at $24–$54 a person a month. I already wrote that teardown. Zapier is the webhook cousin at $30–$69.

How does Retool work

Retool publishes the resource model, the query lifecycle, and the self-hosted container map. I am summarizing those pages, not reconstructing today’s cloud cluster.

A resource is a saved connection. The resources intro says you create one per data source. Host, port, API key, OAuth, default headers. When a query runs, Retool proxies the request server-side with that config. The browser never opens a socket to Postgres or Stripe. Credentials stay on the server. That proxy is why caching can live next to the connector, not in the tab.

A query is an executable block. The queries quickstart says queries are globally scoped and must be triggered. Read queries can run on their own when an input changes. Write queries must be run by an event handler. The last result sits on query.data. Components bind to that with {{ }} expressions, which Retool evaluates as JavaScript.

The query performance page names the hop. The frontend prepares inputs and sends the request. DB_CONNECTOR talks to the resource. Results come back. A transformer can reshape data. Then every component that references the query updates. A table bound to {{ query2.data }} is one of those dependents.

Treat “cloud Retool still splits MAIN_BACKEND from DB_CONNECTOR the same way” as an educated guess. The public picture is the self-hosted architecture. api runs MAIN_BACKEND plus the two connectors, including an SSH variant. Postgres holds apps, resources, users, and audit_trail_events. page_saves stores changes to apps. Do not edit those tables by hand. The docs say that can damage the instance.

Query caching lives inside the connector. Same query, same inputs, still inside the TTL, return the cache. By default that cache is shared across the org. Two people with different auth tokens can get the same rows. Admins can switch that to per-user. Without Redis, the cache sits on the server filesystem. A worker restart can wipe it.

Writes have a second rule. The quickstart describes query variable spoofing prevention. A request that claims current_user.email must match the signed-in user. Otherwise a crafted payload could widen a prepared statement. A v1 does not need their spoofing flag. It needs typed endpoints that ignore extra fields.

Workflows are another product. The architecture page puts a Temporal cluster in the middle. workflows-worker polls for blocks. code-executor runs JavaScript or Python, by default inside nsjail. Resource queries from that sandbox go to workflows-backend, which has its own DB_CONNECTOR. A 4-day v1 does not need Temporal.

The newer AI app builder adds js-executor and an agent-sandbox of gVisor pods, one per editing session. That is the skip row wearing a new name.

BROWSER Lookup, dashboard, queue APP BACKEND Auth, roles, prepare query DB CONNECTOR Saved resource credentials Optional cache, same inputs YOUR DB Postgres, API Never from the tab D1 ROWS User, Role, Audit ApprovalRequest Workflows wait on Temporal Code runs in a jail Skip that half in v1
The browser talks to the app. The connector talks to the data. Workflows sit on the skip row.

A v1 can skip their resource table. Point one server-side lookup at the database you already have, or keep the records in D1. The card’s stack is Astro, HTMX, and D1. Company OAuth is the login.

Screens of a Retool alternative

Three surfaces for v1. If the agent starts a component palette, send it back.

The lookup is home. A search field, a record, an action. Name, plan, last invoice. A viewer sees a masked card. Reveal is its own request, and it writes an audit row. The guardrail on the card is the useful sentence: route every write through validated, permission-checked endpoints recorded in an append-only audit log, and never expose raw SQL to the browser.

WIREFRAME · LOOKUP [email protected] FIND Ada C. · cus-ada Plan bootcamp · invoice 1842 Card ·••• 4242 · reveal Last charge $180 · Oct 12 REQUEST REFUND
Home is one record. Reveal and refund are separate, audited actions.

The dashboard is the handful of numbers the team already checks. Pending approvals. Refunds this week. Failed jobs. No chart builder. No metric marketplace. A number is a query you wrote.

WIREFRAME · DASHBOARD 3 PENDING $540 REFUNDS 1 FAILED Marco requested refund 1842 Ada reveal · card last four
Three numbers you already ask for. Recent audit rows sit under them.

The queue is pending, approved, rejected. The requester cannot decide their own row. Two approvers clicking at once produce one winner. The loser sees who decided, and when. Execution is a second step with its own idempotency key. The Backdesk mini-prompt on the page is that race.

WIREFRAME · QUEUE Refund $180 · Ada · pending Marco · invoice 1842 Approve · reject Credit $40 · approved Lea decided Oct 29 16:12 Plan change · rejected Already decided by Sam
One pending row you can decide. Already-decided rows keep the winner.

How a Retool alternative approval works

The loop is find a record, request a write, wait, then one execution.

Marco searches [email protected]. The app checks his role, loads the customer through a server query, and masks the card. He submits a $180 refund. That write does not hit Stripe yet. It inserts apr-refund-1842 as pending and an audit row for the request.

Lea opens the queue. She is not Marco. Approve is a conditional update that succeeds only while the state is pending. The refund endpoint then runs once, with a key tied to that request id. A retry after a timeout is a no-op. A second Lea tab loses the race and sees the first decision.

FIND THE RECORD Role check, then a masked row SUBMIT A REQUEST Pending, no Stripe call yet CLAIM THE DECISION Four eyes, one winner EXECUTE ONCE Idempotency key on the id APPEND THE AUDIT Request, decision, execution No update path on old rows
The 4-day v1 is lookup, pending request, one decision, one execution, three audit rows.

Roles wait on the 2-week row if you only have two people. Add them before a third person joins. Viewers look up. Editors request. Approvers decide. The requester identity comes from the session, not from the form.

The hard half of a Retool alternative

The skip row starts when anyone on the team can draw a new app.

Retool’s product is a builder. Components on a canvas. Queries in an IDE. {{ table1.selectedRow.email }} wired into a resource. Permission groups sit on apps, resources, workflows, and agents. Resource access is Use, Edit, or Own, and it is per environment. Use lets you run queries. It does not limit which rows those queries return. Row rules are a separate access-policy product.

That is a general-purpose platform. Every new data source is another resource type, another auth flow, another GUI query mode so someone does not DROP TABLE from SQL mode. The resources intro lists API keys, OAuth 1 and 2, AWS IAM, digest, service accounts, and custom multi-step auth. A v1 needs the one database you already open.

The expression language is the other trap. Once the browser can shape a query with {{ }}, you inherit their spoofing problem. You also inherit a live dependency graph. The performance page says post-processing time grows with every component that reads query.data. A hand-built page does not have that graph.

Workflows plus Temporal plus a sandboxed executor are a third company. Make is $10–$29 a month if the rent is a visible pipeline. I already wrote the Zapier teardown if the rent is a webhook and an HTTP action.

4-DAY V1 Lookup, dashboard, queue Typed writes, no raw SQL An append-only audit log SKIP THIS HALF Drag-and-drop and a query IDE Every resource and its OAuth Temporal, jail, plugin system
Ship the three screens. Leave the builder, the connector zoo, and the workflow mesh on the skip row.

I would rebuild Retool for the two lookups we already run in a SQL client. Customer by email. Refund that needs a second person. A dashboard with three numbers.

I would not let the rest of the company paint new apps. I would not paste SQL into a browser.

Host it next to the product, on Node.js and Astro, with HTMX on the three pages, because that is the stack on the card. Use TanStack Start if React is your weekday language. The hosting post already covers D1 and a Worker in front of a private database. Persist users, requests, and audit rows in D1. Keep production data where it already lives, and reach it only from the server.

If the rent is a typed table the team edits all day, that is Airtable, 3 days. If it is “this webhook then that HTTP call”, that is Zapier, 3 days.

Start with the first row

Go to Build your own Retool. Copy the Astro prompt, or TanStack Start if that is what you write.

Tell the agent the first estimate only: record lookup, ops dashboard, approval queue. Four days.

If twelve coworkers already ship internal tools on a shared canvas, keep paying.

Keep reading

Read all articles →