redux-toolkit
redux-toolkit copied to clipboard
Namespace Support for `injectEndpoints` in Microfrontend Projects
Hi everyone! We're running into a challenge similar to #3350 in our project, and we’d love to get your thoughts on a possible solution.
What’s Happening
We’re working on a big project with 40 microfrontends (MFs), all coordinated by a root project using a microfrontend setup. Each MF is built by a separate team, and they don’t know what the others are doing, which is where things get tricky.
The Setup
All our core configs, including the baseApi for RTK Query, live in the root project. Each MF adds its own queries using baseApi.injectEndpoints. Since the MFs don’t talk to each other, we sometimes end up with duplicate query names (like getUser in both auth and profile MFs). This causes clashes, and hooks like useGetUserQuery get overwritten, which is a bit of a headache. 😅
Right now, we don’t have a great way to catch these clashes during development, and with 40 teams working independently, coordinating endpoint names manually is super tough.
Our Naming Convention Try
We tried fixing this by adding module prefixes to endpoint names (e.g., auth_getUser, profile_getUser). It works to avoid clashes, but the auto-generated hook names (like useAuth_GetUserQuery or useProfile_GetUserQuery) get really long and clunky. This makes our code harder to read and slows us down as developers. We’d love a cleaner way to handle this!
Previous Issue and Our Goal
We saw in #3350 that a throw feature was added, which catches duplicate endpoints at runtime by throwing an error. That’s helpful for spotting issues, but it still means runtime errors, which can disrupt the user experience and are tricky to debug in our microfrontend setup. On the other hand, when overrideExisting: true, duplicates don’t cause a clash because one endpoint overrides the other—but we don’t want to override endpoints at all. We’d love to prevent duplicates entirely during development so we avoid both runtime errors and unintended overrides.
The Idea
RTK Query puts endpoints under api.queries by default. What if we could add an optional namespace parameter to injectEndpoints to organize endpoints like api.queries.[namespace].[queryName] or api.queries.[namespace]_[queryName]? This could prevent duplicates and keep hook names tidy. For example:
baseApi.injectEndpoints({
namespace: 'auth',
endpoints: (builder) => ({
getUser: builder.query({ ... }), // Stored as api.queries.auth.getUser or Stored as api.queries.auth_getUser
// Generates hook: useGetUserQuery
})
});
This would:
- Add the namespace to endpoint names (e.g.,
auth.getUserbehind the scenes). - Create readable hooks (e.g.,
useGetUserQuery). - Keep endpoints neatly organized (e.g.,
api.queries.auth.getUser), so no duplicates with other MFs.
Another option could be a warning in development mode or a tool to spot duplicate names before we even build. What do you think?
Steps to Reproduce
- Set up a
baseApiwithcreateApiin the root project. - In one MF (like
auth), add an endpoint calledgetUserusingbaseApi.injectEndpoints. - In another MF (like
profile), add anothergetUserendpoint. - With
overrideExisting: true, see that the second endpoint silently overwrites the first, messing up hooks likeuseGetUserQuery. WithoverrideExisting: false, see a runtime error.
What We’d Love
- A way to prevent duplicate endpoint names during development, maybe with namespacing or dev-time warnings, so we avoid both overrides and runtime errors.
- Hook names that stay clean and easy to read, even with namespacing.
Our Current Workaround
We’re prefixing endpoint names (e.g., auth_getUser, profile_getUser), but this leads to bulky hook names like useAuth_GetUserQuery. We’re also using ESLint rules to catch duplicates during development, but it’s tough to keep 40 teams in sync, and mistakes still may happen. The overrideExisting: true or false option doesnt throw runtime errors but causes different issues, but we’d really like to prevent these issues earlier.
A Bit More Context
Since our teams work independently, it’s hard to make sure everyone uses unique endpoint names without some kind of central system. We think a namespace feature would fit perfectly with RTK Query’s flexibility, avoid runtime issues, keep hooks readable, and make life easier for big, distributed teams like ours. 😊
Related Issue: #3350
If your teams really don't talk to each other, they aren't aware of the other's endpoints at all and also not use/invalidate endpoints from another team, right?
In that case it might have sense to treat them as individual apis and actually have one createApi call per team.
although the caveat to that is that every single createApi instance adds another middleware to the store, which means more function calls on every dispatch, and that will add a lot of overhead. I personally wouldn't want to see more than 2-3 API middleware added to any given store. You said you have 40 microfrontends, so that absolutely should not be configured to have 40 separate API instances each with their own middleware added to the store.
If your teams really don't talk to each other, they aren't aware of the other's endpoints at all and also not use/invalidate endpoints from another team, right? In that case it might have sense to treat them as individual apis and actually have one
createApicall per team.
They sometimes mount at the same time and sometimes interact each others' invalidation. So their CI/CD operations are independent but, they sometimes touches eachother. Especially when need invalidating
although the caveat to that is that every single
createApiinstance adds another middleware to the store, which means more function calls on everydispatch, and that will add a lot of overhead. I personally wouldn't want to see more than 2-3 API middleware added to any given store. You said you have 40 microfrontends, so that absolutely should not be configured to have 40 separate API instances each with their own middleware added to the store.
Just to clarify, our setup uses a single baseApi instance defined in the root project(orchestrator), shared across all 40 microfrontends. Each MF injects its endpoints using baseApi.injectEndpoints, so we only have one API middleware in the store. The namespace proposal is meant to organize endpoints (e.g., api.queries.auth.getUser) within this single instance to prevent clashes, without adding multiple createApi instances. Does that address your concern, or am I missing something? I dont want lots of middlewares either. Because of singleton injecting, one MF may conflict other MF's query if they have same name.
Yeah, my comment was in response to Lenz's suggestion that "it might make sense to have more than one createApi call".
This is part of the complexity tradeoff of MFEs. If you wish to catch this prior to runtime, I would approach it in your pipelines with linting against the other repos.
Organizationally, you should be doing e2e or integration tests somewhere anyway to ensure your host application works as expected, before it hits production.