
TL;DR: Мы сделали автоматическое подключение Supabase через OAuth, чтобы каждый разработчик мог получить готовую базу данных под свой SaaS без ручного деплоя. Миграции выполняем через Supabase CLI, а работу с данными — через PostgREST.
Зачем всё это
Я развиваю сервис AgentCraft — платформу, которая превращает n8n‑автоматизации в готовый SaaS «из коробки».
AgentCraft подключает Stripe, Supabase, дашборды и систему пользователей — буквально за несколько минут.
Цель — минимизировать количество шагов, которые нужно сделать разработчику, чтобы развернуть свою инфраструктуру.

Когда мы дошли до вопроса автоматического развертывания БД, стало очевидно: нужен инструмент, который:
уже знаком no-code-разработчикам,
предоставляет API, CLI и OAuth,
и не требует ручной настройки PostgreSQL.
Выбор пал на Supabase — популярную open-source платформу поверх PostgreSQL.
Архитектура решения
Наша схема работы выглядит следующим образом:
AgentCraft работает на классической PostgreSQL базе данных на бэкенде
Разработчики регистрируются на AgentCraft и подключают свои вебхуки
Разработчики подключают свою учетную запись Supabase через OAuth
AgentCraft автоматически создает основные таблицы в их Supabase проекте:
Биллинг —
billing_plans,subscriptions,invoicesКонечные пользователи —
users,user_sessionsСтатистика —
webhook_executions,usage_trackingи другие служебные таблицы
Таким образом, разработчик просто нажимает “Connect Supabase” — и получает полноценную инфраструктуру SaaS с базой данных, billing’ом и аналитикой. Как все это выглядит можно посмотреть тут - https://www.loom.com/share/e55bb4d7698547d9a31c676f2a109bb0
Как работает Supabase: инструменты взаимодействия
Supabase предоставляет несколько способов взаимодействия с базой данных:
1. Supabase CLI
CLI — основной инструмент для миграций и управления схемой базы данных.
# Логин через OAuth токен supabase login --token $ACCESS_TOKEN # Привязка к проекту supabase link --project-ref $PROJECT_REF # Создание новой миграции supabase migration new saas_migration # Применение миграций supabase db push --yes
CLI идеально подходит для автоматического деплоя схемы в разных проектах Supabase — ровно то, что нам нужно.
2. PostgREST API
PostgREST — это REST API, которое Supabase автоматически генерирует для всех таблиц PostgreSQL.
GET /rest/v1/users?select=id,email&status=eq.active POST /rest/v1/users PATCH /rest/v1/users?id=eq.{id} DELETE /rest/v1/users?id=eq.{id}
Этот API работает “из коробки” и позволяет AgentCraft взаимодействовать с чужими базами, не имея прямого доступа к PostgreSQL.
3. Management API
Management API используется для получения списка проектов, ключей и метаданных.
Через него мы получаем anon_key, service_key и project_ref для последующей работы.

Сравнительная таблица инструментов Supabase
Инструмент | Назначение | Ограничения |
|---|---|---|
Supabase CLI | Миграции, управление схемой, деплой | Требует локальной установки, работает через OAuth |
PostgREST API | CRUD операции с данными, выборка, фильтрация | Не поддерживает DDL (CREATE TABLE, ALTER TABLE и т.д.) |
Management API | Управление проектами, получение ключей | Не управляет схемой БД |
Прямое подключение PostgreSQL | Полный контроль над БД | Требует service_key, не всегда доступен |
Создание миграций через CLI
В AgentCraft мы используем Supabase CLI для создания и применения миграций.
Вот как это реализовано на Go:
func (h *SaaSHandler) deployDatabaseWithOAuth( ctx context.Context, integration *models.ExternalIntegration, project *models.SupabaseOAuthProject, organization *models.SupabaseOAuthOrganization, productID uuid.UUID, ) (map[string]interface{}, error) { accessToken := *organization.AccessTokenEnc // Применяем миграции через CLI err := h.applyDatabaseTemplatesViaCLI(ctx, accessToken, project.Ref, productID) if err != nil { return nil, fmt.Errorf("failed to apply database templates: %w", err) } return deploymentConfig, nil }
А вот сам процесс применения миграций:
func (h *SaaSHandler) applyDatabaseTemplatesViaCLI( ctx context.Context, accessToken, projectRef string, productID uuid.UUID, ) error { tempDir, _ := os.MkdirTemp("/app", "supabase-cli-*") defer os.RemoveAll(tempDir) // Логинимся в Supabase exec.CommandContext(ctx, "supabase", "login", "--token", accessToken).Run() exec.CommandContext(ctx, "supabase", "link", "--project-ref", projectRef).Run() // Создаем миграцию exec.CommandContext(ctx, "supabase", "migration", "new", "saas_migration").Run() // Записываем SQL os.WriteFile(tempDir+"/migration.sql", []byte(migrationSQL), 0644) // Применяем миграции exec.CommandContext(ctx, "supabase", "db", "push", "--yes").Run() return nil }


Почему не удалось использовать PostgREST для миграций
PostgREST не поддерживает DDL операции — то есть нельзя делать CREATE TABLE, ALTER TABLE, CREATE FUNCTION и т.п.
Причины:
Безопасность — нельзя давать возможность создавать таблицы через HTTP
Назначение — PostgREST предназначен для CRUD, а не для схемы
Именно поэтому мы выбрали Supabase CLI — он безопасен, легитимен и поддерживает OAuth-доступ.

OAuth подключение Supabase
Наша цель - сделать максимально простое подключение БД, как у Lovable.
После того, как разработчик жмет кнопку “Connect Supabase”, происходит классический OAuth flow:
func (h *IntegrationsHandler) HandleSupabaseOAuthCallback(w http.ResponseWriter, r *http.Request) { tokens, _ := h.exchangeSupabaseOAuthCode(request.Code) organizations, _ := h.fetchSupabaseOrganizations(tokens.AccessToken) h.storeSupabaseOAuthData(r.Context(), userID, tokens, organizations) }
Далее мы создаем интеграции для всех доступных проектов пользователя:
for _, org := range organizations { for _, project := range org.Projects { details, _ := h.fetchProjectDetailsFromSupabase(accessToken, project.Ref) h.createIntegration(userID, project.Ref, details.ServiceKey, details.AnonKey) } }

Взаимодействие через PostgREST
После миграции мы используем PostgREST API для CRUD операций с таблицами клиента:
func (c *SupabaseCommon) ExecuteSupabasePostgRESTRequest( ctx context.Context, projectRef, serviceKey, method, endpoint string, payload interface{}, ) ([]byte, error) { url := fmt.Sprintf("https://%s.supabase.co/rest/v1/%s", projectRef, endpoint) req, _ := http.NewRequestWithContext(ctx, method, url, reqBody) req.Header.Set("Authorization", "Bearer "+serviceKey) req.Header.Set("apikey", serviceKey) return c.httpClient.Do(req) }
Практические советы
1. Обработка таймаутов
Supabase может “засыпать” после неактивности — добавьте retry-механику:
for attempt := 1; attempt <= 3; attempt++ { err := h.applyDatabaseTemplatesViaCLI(...) if strings.Contains(err.Error(), "connection") { time.Sleep(time.Duration(attempt) * 5 * time.Second) continue } break }
2. Обновление OAuth токенов
Токены истекают, поэтому мы проверяем их перед каждым деплоем и обновляем при необходимости.
3. Валидация после миграции
Проверяем, что все таблицы созданы корректно:
SELECT EXISTS ( SELECT FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'users' );
Вывод
Интеграция Supabase через OAuth и CLI позволила нам:
автоматизировать развёртывание инфраструктуры SaaS для пользователей,
избавить разработчиков от ручного конфигурирования PostgreSQL,
использовать PostgREST как стандартный REST API поверх готовой схемы.
