Architecture Overview
The client-service is the backend for the Emarsys Mobile Engage SDK. It manages client registration, contact identification, push tokens, and geofences. The service consists of a web process serving REST APIs (v3 and v4) and several Pub/Sub worker processes that handle asynchronous workflows like contact resolution.
System Overview
Fastify :3000] Workers[Pub/Sub Workers] end PubSub[Cloud Pub/Sub] Dynamo[(DynamoDB)] Redis[(Redis)] ExtAPIs[Internal APIs
Push / Contact Data / Predict / SDK Mgmt] SecretMgr[Secret Manager] AMQP[RabbitMQ] SDK -->|REST| Web Web -->|read/write| Dynamo Web -->|publish| PubSub Web -->|fetch| ExtAPIs Web -->|cache / rate-limit| Redis Web -->|secrets| SecretMgr PubSub -->|subscribe| Workers Workers -->|write| Dynamo Workers -->|resolve| ExtAPIs Workers -->|publish| AMQP
Endpoint Flows
Client Registration
POST /v3/apps/:appCode/client
POST /v4/apps/:appCode/client
Registers or updates a client device. V4 additionally creates an anonymous contact on first registration.
Push Token
PUT /v3|v4/apps/:appCode/client/push-token
DELETE /v3|v4/apps/:appCode/client/push-token
Sets or clears the push notification token for a device.
Set Identified Contact
POST /v3|v4/apps/:appCode/client/contact
Sets an identified contact on the client. The contact-id is resolved asynchronously by workers. V4 can optionally wait for the resolution via Redis.
Contact Token Refresh
POST /v3|v4/apps/:appCode/client/contact-token
Refreshes an expiring contact token. V4 can optionally wait for contact-id resolution.
Appless Contact Token
POST /v3/contact-token
DELETE /v3/contact-token
Creates or deletes a contact token without an application context, operating at the merchant level.
App Switching (v4)
POST /v4/apps/:appCode/client/app
Switches a client from one application to another, resetting device state in the source app and re-registering in the target app.
Geo-Fences
GET /v3|v4/apps/:appCode/geo-fences
Returns geo-fence locations for the application, using ETag-based caching.
Component Details
Web Process
The main Fastify HTTP server exposes both v3 and v4 REST APIs on port 3000. Each request passes through a lifecycle of hooks that fetch application metadata, validate the app-code and client-id, and on response publish any state changes and log SDK interactions.
See Processes for details on outputs.
Workers
All workers consume messages from Google Cloud Pub/Sub subscriptions on the client-changes topic, filtered by message attributes. They handle the asynchronous parts of contact resolution and state propagation.
| Worker | Responsibility |
|---|---|
Identified Contact Resolver |
Resolves contact-id from contact-field for known contacts via Contact Data API. |
Anonymous Contact Resolver |
Resolves or creates anonymous contacts via Contact Data API. |
Appless Contact Resolver |
Resolves contacts without an app context. |
Contact ID Writer |
Writes resolved contact-id to DynamoDB and publishes to downstream topics. |
Contact ID Writer (Expired) |
Handles expired contact-id write retries. |
Suite Contact Updater |
Publishes contact updates to RabbitMQ for legacy Suite integration. |
Dynamo Clients Maintainer |
Maintains client state consistency in DynamoDB. |
External Dependencies
| Dependency | Type | Usage |
|---|---|---|
Google Cloud Pub/Sub |
Message broker |
Event distribution between web server and workers. Topics: |
AWS DynamoDB |
Database |
Primary storage for client state and device information. |
Redis (3 clusters) |
Cache / Rate limit |
|
Google Secret Manager |
Secrets |
JWT signing key management. |
Push Service (me-push-web) |
Internal API |
Application configuration and push settings. Results cached in memory and Redis. |
Contact Data API |
Internal API |
Contact field resolution and contact-id lookup. |
SDK Management API |
Internal API |
Application metadata. |
Predict Settings |
Internal API |
Prediction configuration per customer. |
Account Data API |
Internal API |
Account-level data. |
RabbitMQ |
Message broker |
Legacy Suite contact update integration via |
Caching
Application data is cached in two levels: in-memory (L1) and Redis (L2) with a default TTL of 24h. See Caching for invalidation details.
Tokens
The service manages JWT tokens for client state (X-Client-State / EC-Client-State) and contact identity (X-Contact-Token / EC-Contact). See Tokens for details.