You never write SQL by hand in Lovable. Describe the shape of your data in plain English — "users can create posts, each post has a title and body" — and Lovable writes the migration, enables row-level security, grants the correct roles, and gives you type-safe client code.
/Thinking in tables
- 01Nouns become tables: Users, posts, comments, orders — each noun in your app is usually a table.
- 02Relationships become columns: A post belongs to a user, so posts has a user_id column pointing at users.
- 03Ownership drives policies: The row's user_id is what row-level security uses to decide who can read or edit it.
/A generated migration
sql
create table public.posts (
id uuid primary key default gen_random_uuid(),
user_id uuid references auth.users(id) on delete cascade,
title text not null,
body text,
created_at timestamptz default now()
);
alter table public.posts enable row level security;
create policy "read own posts" on public.posts
for select using (auth.uid() = user_id);
create policy "insert own posts" on public.posts
for insert with check (auth.uid() = user_id);Never trust the client
Row-level security is enforced by the database itself. Even if someone manipulates your frontend, they can't read or write rows they don't own.