Backend & API Gateway
How Core API, plugin APIs, and the gateway compose a federated GraphQL endpoint. This guide follows version 3.1.7 (03acdf712c).
Complete Local Setup before running these services. For deployment images, see Deployment.
Services and ports
- Gateway:
backend/gateway/src/main.ts, listens onPORT || 4000. - Core API:
backend/core-api/src/main.ts, listens onPORT || 3300. - Plugin APIs:
backend/plugins/*_api/src/main.ts, for examplesales_apion3305viastartPlugin({ name: 'sales', port: 3305 }). - Internal Apollo Router:
backend/gateway/src/apollo-router/index.ts, listens on127.0.0.1:50000(APOLLO_ROUTER_PORT). Clients use port4000; port50000stays internal.
Registration and composition
- Each service calls
joinErxesGateway({ name, port, hasSubscriptions, meta })after listening. See service discovery. - Registration writes
erxes-service-<name>anderxes-service:config:<name>keys in Redis. In development the address ishttp://localhost:<port>; in production it is the internal service address. - The gateway reads plugin names from
getPlugins()(coreplusENABLED_PLUGINSandENABLED_PLUGINS_ONLY_API), waits for each<address>/graphqlto serve_service { sdl }, then runsrover supergraph composeto buildsupergraph.graphql. - The gateway spawns Apollo Router with that supergraph and proxies
^/graphqltohttp://127.0.0.1:50000./pl:<serviceName>proxies to that plugin;/falls back to Core API.
On first startup the gateway downloads Apollo Router, so the initial run needs internet access. Wait for schema composition before opening the UI.
Requests and tenants
The gateway authenticates each request in backend/gateway/src/middlewares/userMiddleware.ts (x-app-token, erxes-app-token, client-auth-token, Bearer/cookie), then forwards user, portal, and subdomain headers. Backend model creation uses the request subdomain to select the tenant database. See Authentication.
Verify
curl --fail http://localhost:3300/health
curl --fail http://localhost:4000/health
curl --fail http://localhost:4000/graphql \
-H 'Content-Type: application/json' \
--data '{"query":"query Health { __typename }"}'
A gateway health ok does not prove composition finished; the GraphQL query must return data.__typename === "Query".