У каждого мобильного приложения есть бэкенд; вопрос не в том, будет ли он, а в том, кто его построит. Коротко: для MVP, который делает одна команда, с небольшим числом бизнес-правил и простой моделью данных, backend-as-a-service (BaaS) вроде Firebase или Supabase самый быстрый путь. Если есть несколько клиентов (мобильное приложение плюс веб-панель плюс сторонние системы), бизнес-правила, которые обязаны выполняться на сервере, интеграции вроде ERP или электронных счетов, реляционная отчётность и обязательства по месту хранения данных, нужен собственный бэкенд. В большинстве корпоративных проектов правильный ответ гибридный: Firebase для push-уведомлений, отчётов о сбоях и аналитики, собственный API для основных данных и бизнес-правил. В этой статье мы рассказываем, как принимаем это решение в проектах мобильных приложений.
Что делает бэкенд в мобильном приложении?
Приложение на телефоне только интерфейс; всё постоянное живёт на сервере. Бэкенд берёт на себя следующие задачи:
- Аутентификация и сессии: кто пользователь, с какого устройства он вошёл, когда заканчивается сессия.
- Хранение и выборка данных: заказы, сообщения, профили, включая случай, когда два пользователя одновременно меняют одну запись.
- Бизнес-правила: расчёт цены, списание остатков, цепочки согласования, проверка лимитов. Выполнять их на клиенте дыра в безопасности.
- Файлы и медиа: загрузка фото, изменение размера, права доступа.
- Уведомления и отложенные задачи: push, почта, ночные отчёты.
- Интеграции: платёжный провайдер, доставка, бухгалтерия, ERP; ключи этих соединений нельзя класть в мобильную сборку.
Готовый бэкенд-сервис очень хорошо закрывает первый, второй и четвёртый пункты, а третий и шестой только с дополнительным кодом. На этом разрыве и строится решение.
Что даёт BaaS (Firebase, Supabase) и чего не даёт
Firebase это набор сервисов, размещённых Google: Authentication, Firestore (документная база), Storage, Cloud Functions, Cloud Messaging (push), Crashlytics и Analytics. Supabase строит похожий набор поверх PostgreSQL и имеет открытый код. В обоих случаях вы не управляете серверами; приложение подключается к базе напрямую через SDK, а правила доступа задаются на стороне сервиса. Что вы получаете, понятно: первый релиз за дни, а не недели, не нужно писать аутентификацию и синхронизацию в реальном времени, не нужно думать о масштабировании. Чего вы не получаете, проявляется позже: в Firestore нет join и массовой отчётности, модель данных строится вокруг экранов, и каждый новый экран её напрягает; для многошаговых бизнес-правил всё равно пишутся Cloud Functions; перенести данные в другую систему можно, но переход от документной структуры к реляционной отдельный проект. Supabase решает первую проблему, предлагая реляционную базу, но вопрос бизнес-правил и интеграций там тот же.
Ключевое различие: где выполняются бизнес-правила?
В модели BaaS приложение пишет в базу напрямую. Это самая быстрая и самая опасная особенность. Если в приложении заказов телефон считает итоговую сумму и записывает её в Firestore, любой, кто откроет приложение, может изменить эту сумму и отправить; правила безопасности проверяют типы полей и владение, но правило вроде «итог должен равняться сумме цена умножить на количество по всем позициям» трудно выразить читаемо. Решение перенести запись в серверную функцию:
// Cloud Function: итог не берётся с клиента, он вычисляется на сервере
import { onCall, HttpsError } from 'firebase-functions/v2/https';
import { getFirestore } from 'firebase-admin/firestore';
export const createOrder = onCall(async (req) => {
if (!req.auth) throw new HttpsError('unauthenticated', 'Требуется вход');
const db = getFirestore();
const items = req.data.items as { productId: string; qty: number }[];
return db.runTransaction(async (tx) => {
let total = 0;
for (const item of items) {
const snap = await tx.get(db.doc('products/' + item.productId));
if (!snap.exists) throw new HttpsError('not-found', 'Товар не найден');
const product = snap.data()!;
if (product.stock < item.qty) {
throw new HttpsError('failed-precondition', 'Недостаточно остатка');
}
total += product.price * item.qty; // цена из записи, а не с телефона
tx.update(snap.ref, { stock: product.stock - item.qty });
}
const ref = db.collection('orders').doc();
tx.set(ref, { userId: req.auth!.uid, items, total, createdAt: new Date() });
return { orderId: ref.id, total };
});
});В момент, когда вы пишете эту функцию, вы пишете бэкенд; только хостинг у Google. С ростом числа бизнес-правил функции множатся, общему коду и тестам нужен каркас, и проект превращается в собственный бэкенд без чьего-либо решения. Поэтому решение начинается не с «Firebase или свой сервер», а с «сколько моих бизнес-правил обязаны выполняться на сервере». Принципы безопасности мобильной стороны мы описали в статье о безопасности мобильных приложений, а проектирование API в статье REST или GraphQL.
Готовый бэкенд-сервис не убирает бизнес-правила, он лишь меняет место, где они написаны. Когда число правил, обязанных выполняться на сервере, превышает несколько штук, выигранная скорость начинает возвращаться обратно.
От чего растёт стоимость?
BaaS тарифицируется по использованию: чтения, записи, хранение и вызовы функций. У собственного бэкенда фиксированные расходы на сервер и сопровождение. Мы не приводим цифр, потому что два счёта определяются разными вещами, и знать это важнее, чем число. Счёт за BaaS растёт не с числом пользователей, а с моделью данных: если экран списка при каждом открытии читает сотню документов, дневное число чтений на пользователя зависит от дизайна этого экрана, и после запуска это самая дорогая ошибка для исправления. Стоимость собственного бэкенда растёт не с объёмом операций, а со временем команды, которая его пишет и поддерживает. Годовые статьи расходов мы расписали в статье о стоимости поддержки мобильного приложения; о бюджете на первую разработку читайте в статье о стоимости разработки мобильного приложения.
Данные ваши? Переносимость и расположение
Каждый проект на BaaS должен заранее ответить на три вопроса. Первый: в какой стране лежат данные. В проектах Firebase можно выбрать регион, но передача персональных данных за рубеж по турецкому закону о защите данных (KVKK) отдельное обязательство, которое закрывается политикой конфиденциальности и, где требуется, явным согласием (эта статья не является юридической консультацией). Второй: как данные экспортируются. Переход от документной базы к реляционной мы описали в статье о миграции данных; это возможно, но модель данных, построенная вокруг экранов, при превращении в таблицы перепроектируется. Третий: что будет, если сервис закроет функцию. Firebase Dynamic Links был закрыт, и зависевшие от него приложения перестраивали инфраструктуру ссылок. Это не делает сервис плохим; это показывает, что продуктовое решение поставщика может дотянуться до вашего продукта. Зафиксируйте стоимость выхода письменно, прежде чем привязывать критический процесс к одному поставщику.
Тест для решения: три вопроса
Если вы отвечаете «да» хотя бы на два из следующих вопросов, выносите основные данные в собственный бэкенд:
- Будут ли данные использовать другие клиенты, кроме мобильного приложения: веб-панель администратора, дилерский портал, сторонний API, интеграция с бухгалтерией или ERP?
- Есть ли бизнес-правила, обязанные выполняться на сервере: расчёт цен и скидок, резервирование остатков, цепочки согласования, проверка лимитов, упорядоченные транзакции?
- Нужна ли реляционная отчётность: выручка за период, средние показатели на пользователя, управленческие отчёты по нескольким таблицам?
Четвёртый вопрос задаётся на обоих путях: можете ли вы сегодня выгрузить данные одной командой? Если нет, сначала решите это, какую бы модель вы ни выбрали. Если ответов «да» меньше двух, и особенно если вы хотите быстро вывести первую версию на рынок и измерить спрос, BaaS правильный старт; объём MVP мы описали в статье что такое MVP. Если встаёт выбор базы данных, поможет статья PostgreSQL или MySQL.
Гибридная модель: использовать оба
На практике самая распространённая конфигурация такая: Firebase Cloud Messaging для push, Crashlytics для отчётов о сбоях, Analytics для статистики использования; собственный API для идентификации, основных данных и бизнес-правил. В этой модели мобильное приложение вообще не подключается к Firestore; Firebase предоставляет только вспомогательные сервисы на стороне устройства. Настройку push мы описали в статье о push-уведомлениях, а дизайн, который продолжает работать без связи, в статье об офлайн-приложениях. У гибридной модели одно условие: граница должна быть явной. Какие данные принадлежат Firebase, а какие API, должно быть записано с первого дня; иначе одна и та же информация живёт в двух местах, и никто не знает, какая из них верна.
Вывод
Firebase и похожие сервисы настоящие инструменты, ускоряющие первый релиз мобильного приложения; проблема не в инструменте, а в непринятом решении. Когда бизнес-правило приходится переносить на сервер, когда появляется второй клиент или запрашивается первый управленческий отчёт, проект уже превратился в собственный бэкенд, и сделать это осознанно дешевле, чем случайно. Напишите нам через форму запроса, чтобы вместе определить, какие данные вашего приложения где должны храниться; на три вопроса выше мы ответим вместе на первой встрече.