Should I vibe code
Manage structured records in grids, forms, and simple views
Free self-hosting stops at three users and the storage engine is not on GitHub. "Just run theirs" is half an answer.
?
Their verdict, the Plus price and the build-time estimate come from their entry, MIT-licensed. Checked 2026-08-04.
?
Our verdict, the regret score and everything below it. Editorial and unsponsored — nobody can pay to be moved.
The honest answer
why the verdict is what it is
The Baserow entry's advice is to stop building and self-host theirs. Try that here and you find it is only half an answer. SeaTable's free self-hosted licence stops at three users, and the component that actually stores and collaboratively edits your tables — dtable-server — is proprietary; the repository's own licence section says so, and its promise that the source will be uploaded later has been sitting there for years. So you can run it, and you cannot fix it, fork it or grow it without a purchase order. That narrows the options to pay per seat, live inside three users, or build. The third is the trap, and not because a grid is hard. It is because of what a grid becomes. Yours will start as a better spreadsheet, and within a year it holds the supplier list, the shift rota and a customer table, with a public web form writing rows into it, no constraints, no migrations, and a restore path you have never once rehearsed. SeaTable sells snapshot retention as a paid feature at six, twelve and twenty-four months. That is not upselling. That is them telling you what the product actually is.
What actually breaks
not "if". the specific failures.
- The web form, which is by definition an unauthenticated write endpoint on the public internet, and which will be found and used to insert tens of thousands of rows overnight
- The row ceiling, because SeaTable's headline claim is unlimited rows in a single base and your version renders every row into the DOM until somebody pastes in fifty thousand
- Restore, which is a question nobody asks until a Tuesday and which is why snapshot retention is a priced feature on the real product
- Column types, once a text column quietly accepts "0012" and stores 12, or a date column parses 03/04 differently for two people in the same team
- Shared view links, created for one supplier in March and still resolving eighteen months later
- Formulas and scripts, which are user-supplied code running on your server — a base with Python automation in it is remote code execution with a spreadsheet on top
- Concurrent edits, where two people editing the same row without operational transforms means the second save silently wins
- Becoming the system of record, which nobody decides and everybody discovers: the day something else starts reading from your grid, it is production
The base is the shift rota, and it has been the shift rota since about April, when someone rebuilt it in your tool because the spreadsheet had become unusable. On Sunday evening a manager opens the grid on a phone, filters to next week, and deletes what she believes are eight duplicate rows. They are not duplicates — they are the same eight people on a second site — and there is no undo, because your delete is a DELETE. She does not mention it, because nothing looked wrong afterwards. Monday morning is quiet in a way that takes forty minutes to understand: eight people are at home, because the roster your app publishes to is generated nightly from the grid and it published a week with holes in it. You go looking for the before-image and there is none. There is a nightly dump from 02:00, taken after the deletion, and the one from Saturday, which predates twenty other edits nobody wrote down. The technical fix is fifteen minutes of SQL. Working out which of Saturday's rows are still correct takes until the afternoon, and you do it while the operations lead stands behind you asking, reasonably, who signed off on this thing being the rota.
Is that you?
the verdict is a default, not a law
- It is one team, one base, and everybody in it would be equally happy in a spreadsheet
- There is no public form — every write comes from an authenticated person you can name
- You run a nightly export to CSV somewhere outside the application and you have restored from it at least once on purpose
- Nothing downstream reads from it automatically; a human always exports deliberately
- A public form writes rows and you have not thought about rate limits, CAPTCHA or a row ceiling
- Anything else in your business reads from it on a schedule, because that makes it production infrastructure
- It holds staff or customer records and your answer to a deletion request is "I would have to look"
- Deletes are hard deletes and your restore story is a dump you have never restored from
- You are planning to support formulas or scripts written by users, which is arbitrary code execution you have chosen to host
If you build it anyway
the checklist, then the prompt that enforces it
- Soft-delete everything from the first commit. A deleted_at column and a thirty-day recycle bin costs an hour and is the single difference between the incident above and a shrug.
- Keep a before-image for every write: who, when, which row, previous value. An operational database with no audit trail cannot answer the only question anyone asks after a mistake.
- Treat public forms as hostile input. Rate-limit per IP, add a CAPTCHA, cap rows per hour, and make submissions land in a review queue rather than straight into the table people trust.
- Put a hard ceiling on bulk operations. Anything touching more than N rows requires a second confirmation stating the count, and runs in a transaction.
- Enforce column types at the database, not in the UI. A grid that validates in JavaScript is a grid that accepts anything from the API, and you will have an API.
- Give shared view links an expiry and a revocation that takes effect on the next request. A link with no expiry is a permanent unauthenticated read of a live table.
- Do not implement user formulas or scripts. If you must, they run in a sandboxed process with no network, a CPU and memory limit, and no access to the host — and you should assume you will get that wrong.
- Rehearse the restore before anyone else gets a login. Break a row deliberately, time how long it takes to get it back, and write that number down. It is your actual risk profile.
I am building a spreadsheet-style database app — bases, tables, grid views,
web forms and shared links. It will quietly become the system of record for a
team, so build for the day somebody deletes the wrong eight rows.
1. Before any feature work, decide and write down the recovery story: soft
deletes, a recycle bin, and per-row before-images. Implement those first.
2. Every mutation writes an audit row in the same transaction — actor, time,
table, row key, before, after. Unrecorded changes did not happen safely.
3. Deletes set deleted_at. Never issue DELETE from the application. Give me the
restore path before you give me the delete button.
4. Bulk edits run in a transaction, refuse above a configurable row ceiling, and
dry-run the first ten rows. The confirmation must state the total count.
5. Column types are enforced by database constraints, not by the UI. Show me a
direct API write being rejected, not just a form field turning red.
6. Treat web forms as a public write endpoint, because that is what they are.
Rate-limit per IP, add a CAPTCHA, cap submissions per hour, and land
submissions in a review table rather than the live one.
7. Shared view links are opt-in, expiring, revocable on the next request, and
scoped to a single filtered view with an explicit column allowlist.
8. Refuse to implement user-authored formulas or scripts. If I insist, sandbox
them in a separate process with no network access and hard CPU and memory
limits, and tell me plainly that I am hosting arbitrary code execution.
9. Paginate and virtualise the grid from the first commit. Assume a table with
200,000 rows exists on day one.
10. Ship a scheduled export to plain CSV outside the application, and make me
restore from it once before anybody else gets an account.
11. Out of scope: automations, scheduled writes and an auto-generated API over
every table. A cron job with write access is the next incident report.
12. Finish by reminding me that SeaTable Server self-hosts free for three users
and SeaTable Cloud is €9 a seat, and that both already have snapshots, row
permissions and form throttling I am about to reimplement badly.That one keeps you out of trouble. For the prompt that actually builds it, canivibecodeit.com has one.
their build prompt ↗Or don’t build it
the boring option, and the way back out
Sooner than you think, and the arithmetic is unusual here. Free self-hosting covers three users permanently, which is a genuinely good deal if your team is three people and stops being an option the moment it is four. Above that, €9 a seat a month buys snapshot retention, row and column permissions, form throttling and someone else's upgrade path — all things you would build late, badly, and only after the incident that made them obviously necessary. Build your own only if what you want is a narrow, purpose-shaped view over data you already own, which is a good project and is not this product.
$9/mo is cheaper than your weekend.
This one owns its own storage, so the exit is genuinely doable — but only if you keep the export honest. Run a scheduled dump of every base to CSV or JSON, with column types in a sidecar, to somewhere outside the application, and verify it by importing it into something else at least once. What does not come with you are the views, the filters, the form definitions and every shared link somebody bookmarked, so keep view and form definitions as checked-in config rather than rows in a settings table. The test is the same as for any internal tool: switch it off for a day and see whose job stops.
Fully open-source spreadsheet database with permissions, views and an API already written.
Open-source Airtable alternative that owns its own storage and self-hosts without a user cap.
Postgres-backed open-source base with a spreadsheet interface, built for large tables.
Questions
SeaTable is open source, so why not just self-host it?
Because it is only partly open source, and the part that is not is the part that matters. The project's own README splits the licences by component: dtable-web and dtable-events are Apache 2.0, seaf-server is AGPLv3, and dtable-server — the piece that stores your tables and provides collaborative editing — is proprietary, with a note saying the source will be uploaded to GitHub later that has aged considerably. The free self-hosted licence also caps you at three users. It is a real and useful option, it is just not the same option Baserow and NocoDB give you.
Why is this harsher than the Baserow entry but softer than NocoDB Cloud?
Blast radius, and where the rows live. NocoDB's defining feature is pointing a grid at a database you already run, so the homemade version has UPDATE on production — that is what puts it at the top of this cluster. SeaTable and Baserow both own their storage, so the worst case is confined to the tool. SeaTable sits above Baserow because "self-host theirs" is a complete answer for Baserow and a three-user, closed-core answer here, and because SeaTable leans harder on public web forms, which are an unauthenticated write endpoint by design.
What will an agent get wrong first?
Deletes. Asked for a grid, it will implement row deletion as a DELETE statement, because that is what deleting a row means, and nothing about the request suggests otherwise. It will also render the whole table into the DOM without virtualisation, validate column types only in the browser, and give the shared view link a UUID and no expiry. Every one of those is the natural implementation and every one of them is the thing you will wish you had done differently.
Is the public form really that dangerous?
It is the most exposed thing you will ship, and it never looks like it. A form is an unauthenticated write into a table your team trusts, reachable by anyone with the URL, and bots find URLs. Without a rate limit and a per-hour ceiling, one bad night is tens of thousands of junk rows in the middle of your operational data, mixed in with the real submissions from that evening — which is a considerably worse afternoon than simply losing the table.
- GDPR Art. 5 — principles relating to processing, including storage limitation (EU)
- GDPR Art. 32 — security of processing (EU)
Every week, someone ships something they shouldn’t have.
New verdicts, the worst thing that landed in the trap, and the occasional incident report. No other email, ever.
An agent will happily hand you a spreadsheet with UPDATE on production. Postgres has no undo button.
The open-source one already exists. Self-host that instead of rebuilding it.
User-editable formulas are user-supplied code. eval() in a shared doc is RCE with a grid on top.
last reviewed 2026-08-05 · verdict is editorial and unsponsored · shared entry data from canivibecodeit under MIT · not legal advice