Integrating Directus with React breaks on caching and access rights
Integrating Directus with React almost never breaks at the "fetched the data and rendered it" stage. The first failure comes later: a content editor updates a piece of content in the admin panel, but the frontend keeps serving the old version from cache for another day.
The reason is that data is pulled directly from the browser and cached at the CDN or bundler level, without tying invalidation to the record-change event. As a result, the desync between the admin panel and the site persists until the next release, not until the next edit.
The second typical failure is access rights. When requests to Directus come from client-side code, a static token with broad permissions ends up in the build: it is visible in the page source and opens access to collections the user is not supposed to see.
The public role in Directus should expose only permitted fields and records, while everything that requires authorization goes through the application's server layer, where the token never leaves the infrastructure.
The third problem is duplicate requests. React components, during hydration and remounting, hit the same endpoint several times, and direct calls from the browser do not pass through a shared caching layer.
Under active traffic, this turns into extra load on Directus and into inconsistent state across components that are waiting for the same data.
All three failures lie in the same plane: the boundary between client and server is drawn in the wrong place. Let's break down how this is closed at the architecture level, rather than with spot patches.
What the Directus and Next.js combination delivers in practice
Build speed and time to first content
Directus serves content through an API, and Next.js fetches it at build time: catalog, article, and landing pages are built into static files and served from the edge.
In practice, this delivers time to first content within tenths of a second instead of seconds when querying the database on every view.
Incremental regeneration changes the picture: when a piece of content is edited, only the affected page is rebuilt rather than the entire site, so publishing takes seconds instead of minutes.
The class of failures that goes away
When the frontend queries the database directly, a storage outage or a heavy query takes down the entire site. With separated layers, the failure is contained: the pre-built static files continue to be served from cache, and the outage affects only content updates.
This turns an incident from "the site is down" into "edits can wait" — a fundamentally different class of incidents and a different scope of work for the on-call shift.
Performance under load
Static pages do not load the application during traffic spikes: traffic growth hits file serving rather than database queries.
The data model and access rights are described in Directus once, and the frontend receives ready-made structures — less code for parsing responses and fewer discrepancies between the admin panel and the site.
Content updates do not require rolling out a new version of the application, so marketing and editorial teams work independently of the development release cycle.
Operation modes: static, incremental rebuild, live stream
Directus serves content via API, but the method of delivering that content to the frontend determines how quickly an editorial change becomes visible to the visitor and how much load is placed on the server.
In practice, one chooses between three modes — and often combines them on a single page: the catalog is built statically, the product card is updated incrementally, and the availability block is pulled in as a live stream.
| Mode | When it fits | Limitations |
|---|---|---|
| Static | Landing pages, documentation, pages with infrequent edits | Full rebuild on every change; content goes stale between builds |
| Incremental rebuild | Catalogs, blogs, pages with frequent but not instant updates | Requires webhooks from Directus; delay between edit and publication; harder to debug the cache |
| Live stream | Counters, statuses, chats, stock levels | Requires a persistent connection; not indexed by search engines; more expensive in terms of load |
Static gives minimal response time and predictable load, but every edit means rebuilding the entire site. Incremental rebuild removes this limitation: a webhook from Directus on a publication event rebuilds only the affected pages, while the rest remain in the cache.
Live stream covers scenarios where data changes between rebuilds — but it cannot be made the foundation for pages that need to be indexed by search.
Choosing a mode is a trade-off between content freshness, load, and maintenance complexity. A mistake at this stage shows up later: either the editor waits hours for publication, or the server cannot handle rebuilds on every save. Let's break down how to select a mode for a specific section of the site.
How we implement integration: from audit to handover
Implementation starts with an audit, not with code. At this stage we examine the current stack, look at where the data lives and how it reaches the frontend, which sections are updated more often than others, and who on the client's team will work with the content.
The audit produces a map of bottlenecks: data duplication between services, manual exports, pages that get fully rebuilt because of a single edit. Without this map, any integration turns into rewriting by guesswork.
Next we design the data schema — collections, relationships, role-based access rights, fields with validation. The schema is locked in before setup, because changing it after the frontend is connected costs many times more.
- Audit. Inventory of data sources, integration points, and editor scenarios. The output is a prioritized list of bottlenecks.
- Data schema. Model of collections, relationship types, roles and access policies, validation rules on the API side.
- Setup. Connecting the data layer to the application, content delivery modes, caching and invalidation on change events.
- Verification. Tests for queries, permissions, behavior when a source is unavailable; running through editor scenarios from draft to publication.
- Handover. Access credentials, environments, instructions for the content team and developers, walkthrough of typical operations.
- Support. Monitoring of integration errors, schema updates for new sections, responding to load changes.
Each step ends with an artifact that can be verified: an integration map, a schema description, environment configuration, a test report. This removes the main risk — when after launch nobody understands why a page shows outdated data.
Handover includes not only documentation but also a joint walkthrough: your team must be able to add a field or a section without us.
Describe your task — we will come back with an estimate and a plan based on these stages.
Output artifacts: configurations, schemas, regulations
Integrating Directus with the frontend is not a "set it and forget it" affair: the configuration of collections, roles, field permissions, and webhooks lives in the repository and changes along with the product.
That is why, as a deliverable, you receive not a set of scattered settings in the admin panel, but a reproducible package that lets the integration be redeployed from scratch, handed over to another team, or extended without archaeology.
- Directus schema configuration — collections, fields, relations, and types as declarative files in the repository: the schema is spun up on a clean environment with a single command rather than assembled by hand.
- Data and relation schemas — a diagram of collections, relation directions, and delete cascades: you can see what will happen to a record when its parent is deleted, before it happens in production.
- Access policies — roles, permissions for collections and individual fields, row-level filtering rules: an editor sees only their own materials, and the public API serves only published content.
- Build and cache configuration — rules for incremental page regeneration and which content changes trigger it: an edit in Directus updates the relevant pages, not the entire site.
- Webhook and real-time settings — which publication events trigger the frontend, how long it takes for content to reach the visitor, and how an undelivered event is handled.
- Content workflow regulations — which fields are required, what is checked before publication, how a new entity is created: an editor cannot break the layout because the rules are baked into the schema.
- Integration documentation — a map of endpoints, environment variables, the deployment procedure, and rollback to a previous schema version.
- Operations manual — what to do when the cache is out of sync, how to add a field without downtime, and where to look when there is an access error.
Every artifact is versioned alongside the code: a change to permissions or the schema goes through review and is rolled back just like a regular release.
Describe your task — we will come back with an estimate and a plan for which of these documents and configurations you specifically need.
Case study: how we eliminated content desync and sped up builds
What it was like before the changes
The project is a media portal with a catalog and an editorial section: content managers edited materials in the admin panel, and the frontend was built on a schedule.
Edits didn't reach production until the next cycle — an average of 40 minutes of waiting, and for urgent publications the editorial team duplicated the material manually.
The desync between what the editor saw in the interface and what the site served reached 15% of edits per week: some changes were lost during overwriting, and some went to production in an incomplete form.
The build took 11 minutes and rebuilt the entire site from scratch because of a single edit in a product card. Rollbacks happened 2-3 times a week: the content team couldn't predict what exactly would end up in a release and asked to revert to the previous state.
What we changed
We switched the frontend to incremental rebuilds: an edit in a collection is tagged, and only the pages that use it are rebuilt. Full builds remained for changes in templates and navigation.
In parallel, we set up a stream of updates from the admin panel to the frontend — the editor sees the result immediately after saving, without waiting for a cycle.
We added a rollback rule: each release is tied to a content snapshot, and reverting to the previous state can be done in a single operation. Build and publication logs are consolidated into a single panel — you can see which edit triggered a rebuild and how long it took.
What it became
| Metric | Before | After |
|---|---|---|
| Build time after an edit | 11 min | 40-60 sec |
| Share of edit desync | up to 15% | less than 1% |
| Rollbacks per week | 2-3 | occasional, for planned releases |
| Publication delay | up to 40 min | seconds |
The build sped up by abandoning full rebuilds: now only the affected section is rebuilt. The desync is gone because there is a single source of truth — the admin panel — and the frontend receives changes as a stream rather than as a batch on a schedule.
Failures are no longer emergencies: the content snapshot allows returning to a working state without manual reconciliation.
The stack here is secondary — what matters is the scheme: a single content source, targeted rebuilds, and predictable rollback. This approach transfers to catalogs, landing pages, and personal accounts, where content changes more often than code.
How does incremental rebuild differ from a live stream?
Incremental rebuild and live stream solve the same problem — delivering fresh content into a finished page — but they are structured differently and they break differently.
Incremental rebuild works on the server side: when a piece of content changes, only the page that depends on it is marked, and it is rebuilt in the background while visitors receive the previous version from the cache.
A live stream keeps a connection between the browser and the data source open and swaps the block directly in the interface, without a reload and without involving the server cache.
Hence the main difference — the moment of update. Incremental rebuild introduces a delay ranging from a few seconds to a minute: content changes rarely, but the page is served as static and withstands load.
A live stream updates data instantly, but every open connection is a resource that must be maintained, and when the connection drops, the interface must correctly show stale data rather than emptiness.
The choice of mode is determined by the nature of the content, not by developer convenience. A catalog, a blog, a landing page, documentation — these are incremental rebuild: the material changes on a schedule, and delivery speed and resilience to peaks matter.
Monitoring dashboards, chats, order statuses, collaborative editing — these are live stream: here a stale value on screen costs more than the cost of the connection.
In practice, the modes almost always coexist on the same site. The static part is built incrementally, while individual blocks subscribe to a live stream through a client component — this way the page stays fast and critical data doesn't lag.
We separate these zones at the data schema design stage, so we don't rebuild the entire page for the sake of a single counter and don't pull a live connection where a rebuild would suffice.
Common technical concerns when integrating Directus
Before a project starts, the same questions almost always come up: will an external system become a single point of failure, will it withstand peak load, is it really possible to move away from it without rewriting the frontend. Below is a breakdown of each, from an engineering perspective.
Security: will an external service get access to our data?
Access is delineated at the level of roles and collections: the public role is granted only those fields that the frontend actually needs, everything else is closed.
Tokens for server-side requests live in environment variables and do not end up in the client bundle — the browser does not see them. We write access rules for the data rather than "trusting everything that comes from the frontend."
Load: will the system withstand peaks and content growth?
We serve static assets and rarely changing pages from cache and go to the source only for fresh data — as traffic grows, this offloads the bulk of requests. We cover heavy queries with indexes and by limiting the fields in the response.
If the content grows many times over, the bottleneck is visible in advance from metrics, not from user complaints.
Migration: what will happen to the current site and data?
We transfer data in batches, with integrity checks at every step, and keep the old system running until the switchover is confirmed. We describe the schema declaratively — it can be brought up in a new environment with a single command. Rollback is possible at any stage until the previous environment is shut down.
Support: will we be left alone with someone else's system?
We hand over the configurations, the data schema, a description of roles and access permissions, and instructions for typical operations. Our engineers stay in touch for maintenance: updates, incident resolution, and refinement of content models. The system remains manageable even if another team handles the tasks.
Describe your task — we will come back with an estimate and an integration plan.
Let's discuss your task and get back to you with an estimate
To make the estimate substantive rather than an "market average", we need context on the task: how the current system is structured, what data it stores, and which scenarios are critical.
Below is what we clarify during the first conversation and which materials help calculate the scope of work accurately.
- Goal and boundaries. What should change: a new section, Directus integration with the frontend, faster delivery, or a migration to a different data schema. We define what is included in the first phase and what we consciously postpone.
- Current stack and state. Which frameworks and versions are in production, where the services are hosted, how the build and deployment are set up. If the project is already live, we need access to the repository or a brief description of the architecture.
- Data model and content. Which entities and relationships exist now, who edits them and how, which fields are required. This determines the collection schema in Directus and the scope of the migration.
- Scenarios and load. Which pages are cached, where real-time is needed, how many users and requests are expected at peak. This determines the choice between static generation and on-demand updates.
- Constraints and access. Requirements for roles and permissions, work with external services, rules for storing personal data, environments for testing and acceptance.
- Timelines and priorities. What is needed by a specific date and what can be released in parts. This way we will propose a plan that does not block other workstreams.
In response, you will receive an estimate by phase with labor costs, a draft work plan with the release order, and a list of risks that should be addressed before the start.
If there is not enough data yet, describe the task in words, and we will clarify the rest in correspondence or on a call.







