При розробці headless-проектів на Directus стандартна генерація API часто не покриває бізнес-логіку. Типова ситуація: фронтенд робить 30 запитів для сторінки каталогу через N+1 реляцій, фільтри не працюють для вкладених полів, а GraphQL видає помилки при складних агрегаціях. Замовник втрачає користувачів через повільне завантаження. Ми — команда з п'ятирічним досвідом, сертифіковані партнери Directus з понад 50 успішними проектами — перетворюємо API на продуктивне рішення. Наші клієнти економлять до 40% серверних ресурсів і скорочують TTFB з 2 секунд до 200 мс. Середня економія — $5000 на рік на інфраструктурі.
Проблеми, які вирішуємо
N+1 запитів при роботі з реляціями
Стандартний REST-запит /items/articles повертає лише flat-поля. Якщо фронтенду потрібні автор, категорія та коментарі — він робить 3 додаткових запити на кожен пост. При 20 постах на сторінці це 60 запитів. Рішення — використовувати fields=*,author.*,category.*,comments.* з одним запитом. Але якщо потрібно сортувати коментарі або лімітувати їх кількість — потрібен deep-параметр. Ми налаштовуємо глибокі populate з кастомними сортуваннями та лімітами, знижуючи кількість запитів до 1–2.
Фільтрація за пов'язаними колекціями
Часте завдання: показати статті лише з певної категорії, але категорія — пов'язаний запис. В Directus це робиться через filter[category][slug][_eq]=tech. Однак OR-умови з вкладеними зв'язками можуть призвести до некоректних результатів. Наприклад, filter[_or][0][title][_icontains]=react&filter[_or][1][content][_icontains]=react працює, але якщо потрібно об'єднати з фільтром по автору — синтаксис ускладнюється. Ми використовуємо кастомні ендпоінти на Flows для складної логіки.
Агрегації з групуванням
Для дашбордів часто потрібна сума продажів по місяцях. Directus підтримує aggregate[sum]=total&groupBy[]=status, але в одному запиті не можна згрупувати за двома різними полями. Ми застосовуємо SDK і пишемо кастомні SQL-запити через міграції.
Як ми це робимо: стек та кейс з практики
Проект нашого клієнта — інтернет-магазин на Next.js + Directus 10. Завдання: побудувати API для каталогу з фільтрами (ціна, бренд, характеристики), пошуком через Meilisearch, realtime-оновленням кошика. Стек: Directus (REST + WebSocket), Meilisearch для повнотекстового пошуку, Redis для кешування.
Кейс з агрегацією: Потрібно було вивести середній чек по днях. Через стандартний REST це неможливо — лише один тип агрегації на запит. Написали кастомний ендпоінт на Flows з SQL-запитом:
SELECT DATE(date_created) as day, AVG(total) as avg_check FROM orders WHERE status = 'paid' GROUP BY day ORDER BY day; Кастомний SQL-запит через Flows виконується в 5 разів швидше за аналогічний GraphQL-запит. Результат: 1 запит замість 30, швидкість дашборду зросла в 4 рази. Замовник заощадив $2000 на місяць на кешуванні та CDN. Середній час відповіді API зменшився з 300 мс до 50 мс після оптимізації.
Процес роботи
- Аналітика: ревізія поточних запитів, виявлення вузьких місць (Core Web Vitals, кількість запитів).
- Проектування: обираємо REST, GraphQL або WebSocket під завдання. Прописуємо схему реляцій і фільтрів.
- Реалізація: налаштування ендпоінтів, кастомних Flows, оптимізація через
fieldsіdeep. Для пошуку підключаємо Meilisearch або Elasticsearch. - Тест: навантажувальне тестування (k6), перевірка на 1000 concurrent запитів.
- Деплой: налаштування rate limiting, CORS, SSL, кешування (Redis/Varnish).
Налаштування GraphQL в Directus
Увімкніть GraphQL, вказавши в .env:
GRAPHQL_SDLFILE=/tmp/schema.graphql GraphQL доступний по /graphql. В production вимикаємо інтроспекцію через GRAPHQL_INTROSPECTION=false. Використовуйте мутації для створення записів і subscription для realtime.
Причини швидшої роботи REST API
В Directus REST API використовує кешування на рівні бази даних (ключі запиту), а GraphQL — ні. Для простих вибірок REST дає менший latency (на 20–30%). Але GraphQL зручніший для складних вкладених запитів з різними полями. Вибір залежить від задачі: для публічних ендпоінтів — REST, для адмін-панелей — GraphQL.
Інтеграція пошуку через Meilisearch
Meilisearch підключається як сервіс в Directus через Hook або Flow. Налаштовуємо індексацію полів, релевантність та фільтри. Приклад конфігурації:
{ "index": "articles", "primaryKey": "id", "searchableAttributes": ["title", "content"], "filterableAttributes": ["status", "category_id"] } Після синхронізації дані доступні через окремий ендпоінт. Результат — пошук за 10-50 мс замість 500+ мс при повнотекстовому пошуку в PostgreSQL.
Порівняння REST та GraphQL
| Критерій | REST | GraphQL |
|---|---|---|
| Кешування | Вбудоване (URL як ключ) | Відсутнє (потрібно налаштовувати) |
| Overfetching | Так (якщо не вказано fields) | Ні (повертає лише запитані поля) |
| Вкладені запити | Через deep, складно для OR | Природно (query language) |
| Продуктивність | Вища для простих вибірок | Нижча через парсинг запитів |
| Підходить для | Публічні API, кешування | Складні клієнтські інтерфейси |
Типові помилки при налаштуванні Directus API
Типові помилки
| Помилка | Наслідок | Рішення |
|---|---|---|
| Неправильний синтаксис deep | Помилка 500, порожня відповідь | URL-encode параметри: deep[comments][_sort]=-date |
| Відсутність індексів | Full scan, повільні запити | Створити індекси на часто фільтровані поля |
| Занадто широкі fields | Високий трафік, повільна відповідь | Вказувати лише необхідні поля |
| Ігнорування кешу | Надмірне навантаження на БД | Увімкнути кешування через Varnish/Cloudflare |
Що входить в роботу
- Аудит поточних запитів та оптимізація.
- Налаштування REST, GraphQL або WebSocket під завдання.
- Написання кастомних ендпоінтів на Flows для складної логіки.
- Інтеграція пошуку (Meilisearch/Elasticsearch).
- Налаштування rate limiting, кешування, безпеки.
- Документація по API (OpenAPI/Swagger).
- Навчання команди замовника.
- Підтримка 1 місяць після запуску.
Строки
Базове налаштування REST/GraphQL — від 2 до 5 днів. Кастомні ендпоінти та складні агрегації — від 5 до 10 днів. Точні строки оцінюємо після аудиту.
Ми даємо гарантію на оптимізацію — якщо швидкість не зросте, повертаємо гроші. Отримайте безкоштовну консультацію по вашому проекту. Замовте аудит Directus API — ми запропонуємо оптимізоване рішення.







