Field Note

Server Routes Keep Database Keys Out of the Browser

Browser apps should not hold powerful database credentials. A thin server route keeps sensitive keys private while still letting workflows save real records.

There is a moment in every useful prototype where it stops being a mockup.

The screens may still be rough. The admin workflow may still be incomplete. The emails may not be wired yet. But if users can submit applications, requests, signatures, checklists, or other operational records, the system has crossed into a different category.

At that point, browser-only state is no longer enough.

The tempting shortcut is to connect the frontend directly to the database and start saving records from the page. Modern backend-as-a-service tools make that easy, and for harmless public data, direct browser access can be perfectly reasonable.

But for sensitive workflow records, there is a line that should not be crossed: do not put powerful database credentials in browser code.

The Browser Is Not a Secret Place

Anything sent to the browser should be treated as public.

Environment variables with frontend prefixes, bundled JavaScript, network requests, source maps, and client-side configuration can all be inspected. A normal user does not need to know how, but an attacker does.

That matters because many database platforms provide different kinds of keys. Some are designed for browser use with strict row-level permissions. Others, like service-role keys, can bypass those protections and perform privileged actions.

The service-role key belongs on the server. Period.

Use a Thin Server Route

A better first production pattern is simple:

  • The browser submits workflow data to /api/records
  • The server route validates the request
  • The server route uses the private database key
  • The database stores the record
  • The server returns a clean success or failure response

This keeps the frontend clean and keeps the powerful key out of the user’s device.

It also creates one place to add rate limiting, validation, audit events, error handling, and notification triggers later. The first version does not need to do everything. It just needs to put the boundary in the right place.

Make the Data Mode Visible

One small detail makes a big difference during development: show whether the app is actually connected to the database.

If the backend is configured, show that records are saving to the database. If credentials are missing, show that the app is running in local preview mode. Do not let a demo silently pretend records are permanent when they are not.

That kind of status label is not just for developers. It protects the business from accidentally treating a preview as a production system.

Store the Full Payload First

Early production systems often need to move before the perfect normalized schema is finished.

One practical bridge is to store the workflow payload as structured JSON while also extracting the important searchable fields: name, email, status, category, date, record ID, and tenant or customer file ID.

That gives the business persistence now and leaves room to normalize the data later into more detailed tables for signatures, documents, uploads, decisions, communications, and audit events.

The Takeaway

The jump from prototype to production should start with the data boundary.

Do not start with email. Do not start with PDFs. Do not start with a giant admin redesign.

Start by making sure every important action creates a real record, through a server route, with private credentials staying private.

Once the record is permanent, everything else has somewhere solid to attach.