/
Блог Хекслета
/
Код
/

Освойте Supabase

Освойте Supabase

25 июня 2026 г.

8 минут
Освойте Supabase

Supabase: бэкенд на PostgreSQL без сервера — от таблицы до защищённого API

Знакомая сцена. У вас идея приложения и готовый фронтенд в голове. Но прежде чем написать первую кнопку, нужен бэкенд: база данных, API к ней, регистрация и вход, загрузка файлов. Поднять Postgres, написать CRUD для каждой таблицы, прикрутить хеширование паролей, настроить хранилище. Две недели работы — и всё это до того, как вы займётесь собственно приложением.

А ведь половина этого кода — рутина, которая просто повторяет структуру таблиц. Эндпоинт «получить заметки», эндпоинт «создать заметку», эндпоинт «удалить заметку» — и так для каждой сущности. Вы пишете один и тот же слой в каждом проекте.

Supabase убирает эту рутину. Вы создаёте таблицы — и сразу получаете к ним готовый REST API, регистрацию пользователей, хранилище файлов и обновления в реальном времени. Бэкенд-код вы не пишете вообще: фронтенд обращается к базе напрямую через библиотеку, а доступ режут правила на уровне самой базы. Это разница между «две недели до старта» и «таблица готова — приложение можно писать прямо сейчас».

Разберём по шагам: что входит в Supabase, как из таблицы появляется API, как Row Level Security защищает данные и как собрать рабочий бэкенд без единой строки серверного кода.

В основе Supabase — обычный PostgreSQL. Базы данных и SQL разбирают на курсе «Основы SQL» и программах по бэкенду на Хекслете.

Что такое Supabase

Supabase — это набор готовых сервисов вокруг базы данных, который заменяет написание бэкенда вручную. Такой подход называют BaaS, Backend as a Service: бэкенд как услуга. Похожую идею продвигал Firebase от Google, но Supabase построен на открытых технологиях, и в его сердце — PostgreSQL.

Это важная деталь. Под капотом не своя закрытая база, а обычный Postgres — тот самый, что используют в больших системах. Всё, что вы умеете в SQL, работает: связи между таблицами, индексы, представления, триггеры, функции. Вы не запираете себя в проприетарной экосистеме — при желании можно забрать базу и перенести на любой Postgres.

Supabase бывает облачным (создаёте проект на сайте за минуту) и self-hosted (поднимаете на своём сервере, потому что код открыт). Для учёбы и прототипов берут облако с бесплатным тарифом, для боевых систем с особыми требованиями — свой сервер.

Что входит в Supabase

Вокруг базы собрано шесть сервисов. Каждый снимает отдельный пласт работы, который иначе пришлось бы писать руками.

Сервис

Что даёт

Что заменяет

Database

Полноценный PostgreSQL с табличным редактором и SQL

Установку и настройку базы

Auto API

REST API, который генерируется из таблиц автоматически

Написание CRUD-эндпоинтов

Auth

Регистрацию, вход, OAuth, восстановление пароля

Самописную систему входа

Storage

Хранилище файлов с доступом по правилам

Настройку файлового хранилища

Realtime

Подписку на изменения таблиц по веб-сокетам

Собственный механизм обновлений

Edge Functions

Серверные функции для своей логики

Отдельный сервер под мелкие задачи

supabase_01_overview.png

Главное в этом списке — связка первых двух пунктов. База и API не разные системы: API напрямую отражает то, что лежит в базе. Поменяли структуру таблицы — API поменялся сам. Не нужно держать синхронными код базы и код эндпоинтов, как в обычном бэкенде.

База данных: обычный Postgres с удобным редактором

Сердце Supabase — база. Работать с ней можно двумя способами, и оба полезны.

Табличный редактор похож на электронную таблицу: создаёте таблицы и колонки мышкой, задаёте типы, связи и ограничения через интерфейс. Удобно на старте и для тех, кто только осваивает базы.

supabase_04_studio.png

SQL-редактор — для всего остального. Это полноценный доступ к Postgres: пишете запросы, создаёте индексы, функции, политики доступа. Создание таблицы заметок выглядит обычным SQL:

create table notes (
  id         bigint generated always as identity primary key,
  user_id    uuid references auth.users not null,
  title      text not null,
  content    text,
  created_at timestamptz default now()
);

Обратите внимание на references auth.users — таблица заметок сразу связана со встроенной таблицей пользователей. Это та самая интеграция, ради которой берут Supabase: база, API и аутентификация знают друг о друге.

Автогенерация API: создал таблицу — получил эндпоинты

Вот главная экономия времени. Как только таблица создана, Supabase сам поднимает к ней REST API. Никакого кода писать не нужно — эндпоинты уже работают.

Операция

HTTP

Что делает

Получить записи

GET

Читает строки, с фильтрами и сортировкой

Создать запись

POST

Добавляет новую строку

Изменить запись

PATCH

Обновляет существующую

Удалить запись

DELETE

Удаляет строку

supabase_02_tableapi.png

На практике к API обращаются не голым HTTP, а через клиентскую библиотеку — она есть для JavaScript, Python, Dart и других языков. Работа с заметками с фронтенда выглядит так:

import { createClient } from '@supabase/supabase-js'

const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY)

// получить свои заметки
const { data, error } = await supabase
  .from('notes')
  .select('*')
  .order('created_at', { ascending: false })

// создать заметку
await supabase
  .from('notes')
  .insert({ title: 'Идея', content: 'Собрать бэкенд на Supabase' })

// удалить по id
await supabase.from('notes').delete().eq('id', 42)

За этими вызовами стоит обычный REST: библиотека собирает HTTP-запрос с фильтрами и заголовками. Но писать его руками не нужно — фильтры, сортировка, постраничный вывод и связи между таблицами доступны методами библиотеки. Серверного кода в этой схеме нет вообще: фронтенд говорит с базой напрямую.

Не только REST

REST — основной, но не единственный способ. Из той же схемы Supabase поднимает и GraphQL — удобно, когда нужно за один запрос вытащить связанные данные из нескольких таблиц. А если логику хочется держать в базе, к ней пишут функцию на SQL и зовут её из клиента как обычный метод — это называется RPC, вызов процедуры. Сложная выборка прячется в функцию, а клиент просто получает результат:

// вызов функции базы из клиента
const { data } = await supabase.rpc('notes_stats', { owner: userId })

Так тяжёлые запросы не размазываются по фронтенду, а живут в одном месте — в базе, рядом с данными.

Row Level Security: почему прямой доступ к базе безопасен

Здесь возникает резонный вопрос. Если фронтенд обращается к базе напрямую, что мешает любому пользователю запросить чужие заметки или удалить всё подряд? Ключ к ответу в браузере виден всем — открыл инструменты разработчика и увидел.

Защищает Row Level Security (RLS) — встроенная возможность PostgreSQL ограничивать доступ к строкам таблицы по правилам. API открыт всем, но база отдаёт каждому только то, что ему разрешено. Правила (политики) пишут на SQL и хранят в самой базе. Никакой серверный код их не обходит.

supabase_03_rls.png

Сначала RLS включают для таблицы. Пока он выключен, а таблица открыта наружу — данные доступны всем, и это самая частая и опасная ошибка новичка.

-- включаем защиту строк
alter table notes enable row level security;

Дальше пишут политики — по одной на операцию. Вот политика, которая разрешает читать только свои заметки:

create policy "Только свои заметки на чтение"
on notes for select
using ( auth.uid() = user_id );

Магия в функции auth.uid() — она возвращает идентификатор вошедшего пользователя из его токена. Условие auth.uid() = user_id означает: отдай строку, только если её владелец — тот, кто запрашивает. Двое пользователей делают один и тот же запрос select * from notes, но каждый получает только свои строки. База разбирается сама, на уровне каждой строки.

Политики ставят на каждую операцию отдельно. Для вставки проверяют, что пользователь записывает заметку на своё имя:

create policy "Создавать только свои"
on notes for insert
with check ( auth.uid() = user_id );

Главная ловушка Supabase — забыть включить RLS. Таблица открыта наружу, защиты нет — и любой желающий читает и меняет все данные через публичный ключ. Это причина большинства громких утечек из проектов на Supabase. Правило простое: включили RLS на каждой таблице, к которой есть доступ снаружи, и проверили, что политики действительно работают.

Два ключа: что можно во фронтенде, а что нельзя

У проекта Supabase два ключа доступа, и путать их опасно.

Ключ

Где использовать

Подчиняется RLS

anon (публичный)

Во фронтенде, в браузере — это нормально

Да — отдаёт только разрешённое

service_role (служебный)

Только на сервере, в защищённой среде

Нет — обходит все политики

Публичный ключ безопасно держать во фронтенде именно потому, что он подчиняется RLS: даже зная его, посторонний получит только то, что разрешают политики. А вот служебный ключ обходит защиту полностью — он для доверенного серверного кода и в браузер попадать не должен никогда. Утёкший служебный ключ означает полный доступ ко всей базе.

Аутентификация: вход из коробки

Регистрация и вход в Supabase встроены и связаны с базой. Пользователи живут в таблице auth.users, при входе сервис выдаёт токен, а функция auth.uid() в политиках берёт идентификатор пользователя именно из него. Всё это работает вместе без настройки.

// регистрация
await supabase.auth.signUp({
  email: 'nikita@hexlet.io',
  password: 'secret123'
})

// вход
await supabase.auth.signInWithPassword({
  email: 'nikita@hexlet.io',
  password: 'secret123'
})

После входа библиотека сама прикладывает токен ко всем запросам к базе. Поэтому политики с auth.uid() начинают работать автоматически: пользователь вошёл — и видит только свои данные. Кроме почты и пароля поддерживается вход через Google, GitHub и другие сервисы, вход по ссылке из письма и одноразовые коды — всё включается настройкой.

Хранилище и реальное время

Storage хранит файлы: аватары, документы, картинки. Файлы лежат в бакетах — это контейнеры, вроде папок верхнего уровня. Доступ к файлам режут те же политики, что и к таблицам, поэтому свой аватар пользователь меняет, а чужой — нет. Загрузка файла так же проста, как и работа с базой:

await supabase.storage
  .from('avatars')
  .upload('nikita/photo.png', file)

Realtime даёт подписаться на изменения таблицы. Кто-то добавил строку — все подписчики мгновенно узнают об этом по веб-сокету. Так делают чаты, совместное редактирование, живые ленты — без опроса сервера в цикле:

supabase
  .channel('notes-changes')
  .on('postgres_changes',
    { event: 'INSERT', schema: 'public', table: 'notes' },
    (payload) => console.log('Новая заметка:', payload.new))
  .subscribe()

Практика: бэкенд для заметок без сервера

Соберём рабочий бэкенд приложения заметок. Серверного кода — ноль.

Шаг 1. Создать проект. Заводите проект на supabase.com — получаете базу, URL и публичный ключ.

Шаг 2. Создать таблицу. В SQL-редакторе выполняете создание таблицы заметок со связью на auth.users — тот же SQL, что был выше.

Шаг 3. Включить защиту и добавить политики. Без этого шага данные открыты всем:

alter table notes enable row level security;

create policy "Читать свои" on notes
  for select using ( auth.uid() = user_id );

create policy "Создавать свои" on notes
  for insert with check ( auth.uid() = user_id );

create policy "Удалять свои" on notes
  for delete using ( auth.uid() = user_id );

Шаг 4. Подключить фронтенд. Регистрируете пользователя, входите и работаете с заметками. Поле user_id можно проставлять политикой или значением по умолчанию, чтобы клиент его не передавал:

const supabase = createClient(URL, ANON_KEY)

await supabase.auth.signInWithPassword({ email, password })

// благодаря RLS вернутся только заметки вошедшего пользователя
const { data } = await supabase.from('notes').select('*')

Готово. У вас есть база, защищённый API, регистрация и вход — и ни одной строки серверного кода. Чтобы получить то же самое классическим путём, ушла бы та самая пара недель из начала статьи.

Архитектура: с сервером и без

Чем подход Supabase отличается от привычного, видно по тому, через что проходит запрос.

В классической схеме посередине стоит ваш сервер: приложение зовёт сервер, сервер ходит в базу, проверяет права в коде и возвращает ответ. Сервер нужно написать, развернуть, поддерживать и масштабировать.

supabase_05_arch.png

В схеме Supabase сервера-посредника нет. Приложение обращается прямо к Supabase, права проверяет сама база через RLS. Меньше звеньев — меньше кода и меньше мест, где что-то ломается. Цена за это — меньше контроля над сложной логикой, и тут на помощь приходят Edge Functions, когда без своего кода всё же не обойтись.

Антипаттерны

Открыть таблицу наружу без RLS. Самая дорогая ошибка: данные доступны всем, кто знает публичный ключ, а он виден в браузере. RLS включают на каждой таблице с внешним доступом и проверяют политики до выхода в прод.

Положить служебный ключ во фронтенд. Браузер не умеет хранить секреты. Служебный ключ обходит все политики — в браузере он означает полный доступ к базе для любого. Во фронтенде только публичный ключ.

Считать, что Supabase заменяет знание SQL. Под капотом обычный Postgres, и без понимания связей, индексов и политик быстро упираешься в потолок. Supabase убирает рутину, но не отменяет базы данных как тему.

Вся логика во фронтенде. Когда нужны вычисления, которым нельзя доверять клиенту, или работа со сторонними сервисами — это задача для Edge Functions или функций базы, а не для браузера. Не всё стоит тащить на клиент.

Не закладывать запас на рост. Бесплатный тариф щедрый, но у него есть пределы по размеру базы и трафику. Для проекта, который планирует расти, лимиты тарифов стоит посмотреть заранее, а не в день, когда упрётесь.


FAQ

Supabase бесплатный?

Есть щедрый бесплатный тариф — его хватает для учёбы, прототипов и небольших проектов. Дальше идут платные тарифы по размеру базы, трафику и числу активных пользователей. Код открыт, поэтому Supabase можно поднять и на своём сервере, заплатив только за инфраструктуру.

Чем Supabase отличается от Firebase?

Firebase от Google построен на собственной NoSQL-базе и закрыт. Supabase стоит на открытом PostgreSQL — это реляционная база с SQL, связями и транзакциями. Кому ближе привычный SQL и кто не хочет привязываться к одному поставщику, выбирают Supabase. Firebase сильнее в мобильной экосистеме Google.

Нужно ли знать бэкенд, чтобы начать?

Базовое понимание баз данных обязательно — Supabase убирает рутину, но не саму тему. Достаточно понимать таблицы, связи и SQL на уровне основ. Серверное программирование на старте не нужно: его роль берут на себя автогенерация API и RLS.

Можно ли использовать Supabase с любым фронтендом?

Да. Клиентские библиотеки есть для JavaScript, Python, Dart, Swift и других языков, а под капотом обычный REST, к которому можно обратиться из чего угодно. React, Vue, мобильное приложение, скрипт на Python — всё работает одинаково.

Что делать, когда нужна сложная серверная логика?

Для логики, которой нельзя доверять клиенту, есть два пути. Edge Functions — серверные функции на стороне Supabase для своего кода. Функции и триггеры самой базы — для логики, которая ближе к данным. Прямой доступ к базе и эти инструменты дополняют друг друга, а не исключают.

Не привязывает ли Supabase к себе?

Меньше, чем закрытые аналоги. В основе обычный PostgreSQL, и базу можно выгрузить и перенести на любой другой Postgres. Привязка есть на уровне сервисов — Auth, Storage, Realtime придётся заменить при переезде, но данные и схема остаются стандартными и переносимыми.

Никита Вихров

2 дня назад

0

+7 800 100 22 47

бесплатно по РФ

+7 495 085 21 62

бесплатно по Москве

108813 г. Москва, вн.тер.г. поселение Московский,
г. Московский, ул. Солнечная, д. 3А, стр. 1, помещ. 20Б/3
ОГРН 1217300010476
ИНН 7325174845