ZapBounce and Supabase

Supabase gives the browser direct database access through PostgREST, which is the feature and the constraint. Anything the client can read, the client can read.

So the verification key belongs in an edge function, and the verdicts table needs row-level security that does not expose one user's data to another.

The client talks to the database directly

In a conventional stack, a server sits between the browser and the data. In Supabase the browser holds an anon key and queries PostgREST, so RLS is the only thing separating users.

A verdicts table created without RLS is readable by every authenticated user, which turns a hygiene table into a list of your customers' email addresses.

The API key has the same problem in a different shape. Calling the verify endpoint from client code publishes the key to every visitor.

How the data moves

  1. Call the API from an edge function

    The key lives in the function's secrets, never in client code or in a table.

  2. Enable RLS on the verdicts table before inserting anything

    A table created without it is open by default in practice, and the window between creation and the policy is the exposure.

  3. Use the service role only inside the function

    The edge function writes verdicts with the service role; the client reads through a policy that scopes to its own rows.

  4. Batch through a scheduled function

    pg_cron triggering an edge function handles the recurring pass without an external scheduler.

Setting it up

  1. Create the verdicts table and enable RLS in the same migration.
  2. Write a policy scoping reads to the owning user, and no client write policy at all.
  3. Store the API key as an edge function secret.
  4. Write an edge function that verifies an address and inserts the verdict with the service role.
  5. Call that function from the client rather than calling the verification API directly.
  6. Schedule a recurring pass with pg_cron invoking a second function for the batch job.

Supabase: common questions

Can I call the verify API from the browser?

No. The key would be public to every visitor. Call an edge function, which holds the key server-side.

When should RLS be enabled?

In the same migration that creates the table. The gap between creating a table and adding a policy is a real exposure window.

How do I schedule a recurring check?

pg_cron invoking an edge function. No external scheduler needed.

Check a Supabase export today

100 free checks a month, no card. Unknown results and duplicates are never billed.