При разработке экзаменационной платформы для технического вуза мы столкнулись с требованиями: 10 000 студентов, 200 предметов, 50 типов заданий, пиковая нагрузка 500 одновременных сессий. Система должна гарантировать сохранность данных при сбоях и защиту от списывания. Цена ошибки — не просто оценка, а репутация учебного заведения или сертификация специалиста. Рассказываем, как мы решаем эти задачи на практике.
Мы проектируем модульную архитектуру, где каждый тип экзамена изолирован в свой сервис: автопроверяемые тесты, задания с ручной проверкой, адаптивные (CAT) и прокторируемые экзамены. Такой подход упрощает масштабирование и добавление новых типов. Например, для одного заказчика мы реализовали поддержку 12 языков программирования в coding tasks, каждый — в Docker-контейнере с изоляцией.
Типы экзаменов и их компоненты
| Тип |
Особенности |
Количество вопросов в типовом тесте |
| Автопроверяемый |
Тесты, задачи с вариантами, краткие ответы |
30–60 |
| С ручной проверкой |
Эссе, coding tasks, кейсы |
3–10 |
| Адаптивный (CAT) |
Сложность подстраивается под ответы |
15–25 (на 30% меньше, чем линейный) |
| Прокторируемый |
С наблюдателем (online или offline) |
любой |
| Open-book |
Допускается использование материалов |
любой |
Каждый тип требует своих компонентов: для эссе — редактор с проверкой плагиата, для coding tasks — запуск кода в изолированном контейнере. Банк вопросов формируется от 500 до 5000 единиц.
Как устроена защита от списывания?
Режим киоска блокирует 99% попыток переключения вкладок. Реализация через document.onfullscreenchange + детектирование visibilitychange:
document.addEventListener('visibilitychange', () => {
if (document.hidden && examInProgress) {
recordViolation('tab_switch', { timestamp: Date.now() });
}
});
Рандомизация: порядок вопросов и вариантов ответов перемешивается для каждого испытуемого — shuffle_seed генерируется при старте и сохраняется. Вероятность совпадения вариантов у двух студентов — менее 1 на миллион. Лимит времени хранится на сервере, клиент синхронизирует каждые 30 секунд. При истечении времени — автоматическая отправка. Комплекс мер снижает количество нарушений на 80% по сравнению с простым таймером.
Как работает адаптивное тестирование?
Computer Adaptive Testing (CAT) подбирает вопросы на основе оцениваемого уровня. Алгоритм использует Item Response Theory (IRT), согласно Item Response Theory (Wikipedia): каждый вопрос в банке имеет параметры сложности (b), дифференцирующую способность (a) и вероятность угадывания (c). Мы реализуем модель 3PL.
Процесс:
- Начинаем со среднего вопроса (θ = 0).
- Правильный ответ → следующий вопрос сложнее.
- Неправильный → проще.
- Оценка знания (θ) пересчитывается после каждого ответа.
Для расчётов используем библиотеку catirt (R) или самописную реализацию. Результат — точная оценка за 15–25 вопросов вместо 40–60 при линейном тесте, что сокращает время на 40%.
Пример оценки параметров вопроса по IRT
Для каждого вопроса вычисляется трёхпараметрическая логистическая функция: P(θ) = c + (1-c) / (1 + exp(-1.7*a*(θ-b))). Параметры оцениваются методом максимального правдоподобия по калибровочной выборке (не менее 200 ответов на вопрос).
Надёжность и восстановление
Экзамен нельзя потерять. Автосохранение текущих ответов каждые 30 секунд (POST на сервер). При обрыве соединения — продолжение после переподключения с сохранённого состояния. На практике 99.9% сессий завершаются без потери данных. При технической проблеме — процедура повторного допуска (reopening exam session). Ответы хранятся в exam_answers с submitted_at, отдельно от итоговой оценки.
Онлайн-прокторинг
Два уровня:
| Уровень |
Технология |
Точность детекции нарушений |
Относительная стоимость |
| AI-прокторинг |
MediaPipe/OpenCV self-hosted |
70% |
1x |
| Живой прокторинг |
WebRTC |
95% |
3x |
| Гибрид (AI + live) |
Комбинация |
95% |
1.5x |
Self-hosted решение на MediaPipe/OpenCV снижает затраты в 3 раза по сравнению с коммерческими сервисами. Данные с веб-камеры записываются и анализируются постфактум — это снижает нагрузку на сервер во время экзамена.
Что входит в результат
В базовую комплектацию входят: банк вопросов, система автопроверки, античит-модуль, генерация сертификатов, а также документация по развёртыванию и API. Расширенная комплектация дополнительно включает адаптивное тестирование (CAT), прокторинг, интеграцию с LMS, кастомные типы вопросов и обучение до 5 сотрудников. Всегда предоставляем исходный код без ограничений и гарантийную поддержку 3 месяца.
Этапы разработки
- Аналитика: сбор требований, профилирование нагрузки, проектирование архитектуры.
- Проектирование: прототип UI, модель данных, API-спецификация.
- Реализация: итеративная разработка с демо каждые 2 недели.
- Тестирование: нагрузочное до 1000 одновременных сессий, security audit.
- Деплой: развёртывание на вашей инфраструктуре и передача документации.
Сроки и состав работ
| Комплектация |
Срок |
Состав |
| Базовая |
3–4 месяца |
Банк вопросов, таймер, автопроверка, античит, сертификаты |
| Расширенная |
5–8 месяцев |
Всё из базовой + прокторинг, CAT, ручная проверка эссе, интеграции |
В стоимость входит: документация, исходный код, обучение до 5 сотрудников, гарантийная поддержка 3 месяца. Конкретная стоимость рассчитывается индивидуально после анализа требований.
Наша экспертиза
5+ лет опыта в разработке высоконагруженных образовательных платформ. Выполнили 30+ проектов для вузов и онлайн-школ с аудиторией от 500 до 50 000 пользователей. Стек: React/Next.js, Node.js/Nest.js, PostgreSQL, Redis, Docker, Kubernetes. Оценим ваш проект бесплатно — свяжитесь для консультации и получите демо-доступ к прототипу.
Разработка SaaS-платформ
Мы знаем эту боль наизусть. Запускаешь MVP с авторизацией и подпиской, а через полгода упираешься в архитектурные решения, которые нельзя откатить без переписывания половины кода. Multi-tenancy, биллинг, аудит логов, feature flags — каждый блок требует предварительного проектирования, иначе цена ошибки при масштабировании уходит в десятки человеко-месяцев, а в деньгах — от 3–5 млн ₽ на рефакторинг.
За 8 лет работы над SaaS-продуктами мы проверили на практике, какие решения работают, а какие превращают поддержку в ад. Ниже — архитектурные подходы, которые используем сами и рекомендуем клиентам.
Как мы строим multi-tenancy: изоляция без оверхеда
Первое, что решаем — схема разделения данных. Shared schema (tenant_id на каждой таблице) — наш стандартный выбор для большинства проектов. Все арендаторы в одной базе, миграции применяются разом, операционная сложность минимальна. В Laravel реализуем через Global Scope:
protected static function booted(): void
{
static::addGlobalScope('tenant', function (Builder $builder) {
$builder->where('tenant_id', TenantContext::current()->id);
});
}
Глобальный скоуп — только первый уровень защиты. Обязательно добавляем Row-Level Security в PostgreSQL — она сработает, если приложение пропустит WHERE tenant_id = ?:
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation ON orders
USING (tenant_id = current_setting('app.tenant_id')::uuid);
Для enterprise-клиентов, которым нужна физическая изоляция, выделяем отдельную базу. Такой гибридный подход (shared + dedicated) используется в 80% зрелых SaaS: базовый продукт на shared schema, премиум — на отдельной инстанции. Мы внедряем его с первого спринта, чтобы не переписывать логику позже.
Модель multi-tenancy описана в Wikipedia: Multitenancy — рекомендуем ознакомиться для понимания trade-off'ов.
Почему биллинг — самый недооценённый блок
Upgrade посреди расчётного периода, downgrade с отложенным вступлением, истёкший trial, failed payment с grace period — Stripe Billing закрывает 90% сценариев из коробки. Обязательно обрабатываем вебхуки (customer.subscription.updated, invoice.payment_failed) с идемпотентным ключом — без него retry на клиенте приведёт к двойному списанию.
Для рынка СНГ — ЮKassa или Tinkoff recurring. API менее удобны, но покрывают требования 54-ФЗ.
Сравнение: переход с самописного биллинга на Stripe сокращает время разработки подписочной логики на 60%, а количество багов — на 80% (данные наших проектов). Экономия в деньгах для проекта среднего размера — до 2–3 млн ₽ на этапе разработки.
Onboarding: как не потерять пользователя до aha-moment
Технически onboarding — это wizard с persistent состоянием, который нельзя случайно пропустить. Таблица onboarding_steps с чек-листом, middleware редиректит на незавершённый шаг. После завершения — флаг в user settings, middleware отключается.
Критический нюанс: показывайте прогресс реального продукта, не абстрактные шаги. «Создайте первый отчёт» вместо «Завершите шаг 3 из 5». Мы используем drip-кампании через Customer.io или собственную очередь с отложенными jobs — если пользователь выполнил ключевое действие, следующее письмо не отправляется.
Feature flags и управление доступом
SaaS с тарифами требует гранулярного контроля. Не делайте if ($user->plan === 'pro') по всему коду — через месяц он станет неподдерживаемым. Вместо этого:
- Backend: Gate + Policy с проверкой через таблицу
features, связанную с планами.
- Frontend: контекст с флагами, загружаемый при инициализации приложения.
- Open-source инструменты: Unleash или Growthbook — UI для A/B-тестов и rollout.
Как защитить API от агрессивных клиентов
Rate limiting — must-have для публичного API. Один клиент может положить всех остальных. В Laravel используем Redis с sliding window counter:
| Тариф |
Лимит |
Заголовки в ответе |
| Free |
100 req/h |
X-RateLimit-Limit: 100 |
| Pro |
1 000 req/h |
X-RateLimit-Limit: 1000 |
| Enterprise |
10 000 req/h |
X-RateLimit-Limit: 10000 |
Каждый ответ содержит X-RateLimit-Remaining и X-RateLimit-Reset — клиенты рассчитывают на эти заголовки.
Аудит-логи и мониторинг: что, кто и когда
Без аудит-лога невозможно узнать, кто удалил проект или когда изменились настройки биллинга. Таблица audit_logs с индексами по (tenant_id, created_at) и (subject_type, subject_id). В Laravel — Observer'ы на ключевых моделях.
Пример реализации Observer для Model
class OrderObserver
{
public function created(Order $order): void
{
AuditLog::create([
'tenant_id' => $order->tenant_id,
'user_id' => auth()->id(),
'action' => 'created',
'subject_type' => Order::class,
'subject_id' => $order->id,
]);
}
}
Мониторинг: Sentry для exception tracking, Grafana + Prometheus для метрик. Алерты на error rate > 5% и response time p95 > 2s.
Опыт нашей команды и гарантии
Над SaaS-платформами работают инженеры с 8+ летним опытом, за плечами — 50+ проектов, от стартапов до enterprise с миллионными нагрузками. Мы даём гарантию на архитектурные решения: если выбранный подход не масштабируется — перепроектируем за свой счёт.
Deliverables и гарантии
- Документация архитектуры: схемы, ERD, sequence diagrams.
- Настройка CI/CD (GitHub Actions / GitLab CI).
- Доступы к репозиторию, стейджингу и продакшену.
- Обучение команды: 2–3 сессии по код-ревью и runbook.
- Post-launch поддержка 1 месяц.
- Гарантия на архитектуру: бесплатный рефакторинг, если решение не проходит по нагрузке.
Процесс работы
- Discovery (1–2 недели) — аудит текущей архитектуры, скоуп MVP, приоритеты фич.
- Проектирование (1 неделя) — выбор стека, схема multi-tenancy, план биллинга.
- Разработка (4–12 недель) — спринты по 2 недели, демо после каждого.
- Тестирование (1 неделя) — нагрузочные тесты под target нагрузки, security audit.
- Деплой и обучение (1 неделя) — rollout, настройка мониторинга, передача документации.
Ориентиры по срокам
| Этап |
Срок |
| MVP (core features + auth + billing) |
12–16 недель |
| Полноценный продукт с admin panel |
20–28 недель |
| Enterprise SaaS с multi-tenancy + audit |
28–40 недель |
Стоимость рассчитывается индивидуально — свяжитесь с нами, мы оценим проект за 2 дня. Закажите разработку под ключ: от проектирования до деплоя с гарантией архитектуры. Получите консультацию по архитектуре вашего продукта — первый час бесплатно.