Your data, walled off

Restaurant data security that isolates every outlet

Multi-tenant done properly means one outlet’s data is invisible to every other, enforced by the database itself, not a filter the app promises to remember.

The short answer

CountStand keeps each outlet’s data walled off with Postgres row-level security, forced on all 47 tenant tables: a query for one outlet physically cannot return another’s rows, because the boundary lives in the database, not in application code that could forget it. Every query is fully parameterised, so there is no injection seam to prise open, and CSP and HSTS headers harden the browser edge.

47 tables
forced row-level isolation
100%
parameterised SQL, zero injection
₹999
per month, per outlet
01 / What you get

What database-enforced isolation buys you

The boundary between outlets is structural, not a promise in code.

Row-level security, forced on

Postgres RLS is enabled and forced on all 47 tenant tables, so the isolation applies even to the connection the app uses, there is no privileged path that quietly sees everything.

A cross-tenant read returns nothing

Ask for another outlet’s orders and the database hands back an empty set, not a row hidden in the UI. The wall is enforced where the data lives, so a bug in a screen cannot leak across outlets.

Every query parameterised

All SQL is 100% parameterised, values are never concatenated into a query string, so the classic injection attack has no seam to exploit and a stray apostrophe in a dish name breaks nothing.

Hardened at the browser edge

The helmet security-header suite sets a Content-Security-Policy and HSTS, so the front end resists script injection and downgrade attacks before a request ever reaches your data.

What stops one outlet from seeing another’s data?

Most software keeps tenants apart with a WHERE clause the application is trusted to add to every query. Miss it once, a new report, a hurried join, a background job, and one outlet’s numbers surface in another’s screen. CountStand does not rely on that discipline. Row-level security is declared on the table itself, so the rule travels with the data and applies to every query that touches it, everywhere.

Because the check runs inside Postgres, the forced option means even the table owner’s connection obeys it, there is no admin shortcut that sees across the wall. The practical result: a franchise group can run forty outlets on one system, and the Andheri branch cannot read Bandra’s sales, staff or costs, not because a developer remembered to filter but because the database refuses to return the rows.

Is my restaurant’s data safe from injection attacks?

The oldest way into a database is to smuggle SQL through an input field, a booking name, a note, a search box. It works when software glues user text straight into a query. CountStand never does: every statement is parameterised, so the value you type is always treated as data, never as code to run. A quote mark in a customer’s name is just a character, not a break-in.

Layered on top, the helmet header suite tells the browser what it may load and to talk only over HTTPS, shrinking the surface a malicious script could use. None of this is a bolt-on you configure; parameterised access and the header policy ship on by default, on every plan. Security you have to switch on is security someone eventually forgets, so here the safe setting is the only setting.

03 / Questions

Asked by owners like you

How does CountStand keep one outlet’s data separate from another’s?

Postgres row-level security is forced on all 47 tenant tables, so a query for one outlet cannot return another’s rows. The boundary lives in the database, not in app code, so a screen bug can never leak data across outlets.

What is row-level security and why does it matter?

It is a Postgres feature that attaches an access rule to a table, so every query is filtered by the database itself. Forced on, it applies even to the app’s own connection, there is no privileged path that sees every outlet at once.

Is CountStand protected against SQL injection?

Yes. Every database statement is fully parameterised, so anything typed into a field is handled as data, never as SQL to execute. There is no string-building seam for an injection attack to slip through.

Is this data security an enterprise add-on?

No. Forced row-level isolation, parameterised queries and the security-header suite are the foundation of every account, from ₹999/mo per outlet with a 30-day free trial and no card, not a tier you upgrade into.

Keep every outlet’s data its own

Database-enforced isolation ships on every plan, start your 30-day free trial.

30-day free trial · No card · From ₹999/mo per outlet