Client Manager
The Client Manager is a subsystem responsible for the lifecycle management of device (client) data across multi-tenant PostgreSQL schemas. It consists of multiple independent sub-workers, each handling a specific aspect of device data management.
Multi-Tenant Architecture
Each customer’s device data is stored in an isolated PostgreSQL schema named tenant_<customerId>.
The TenantSchemaManager class handles schema creation, migration, and deletion.
Sub-Workers
Writer
-
Subscription:
client-manager.writer -
Processes device registration and update events from Pub/Sub
-
Writes device data to the appropriate tenant schema in PostgreSQL
-
On transient failure, publishes the message to the Republisher for retry
-
On permanent failure, publishes to
client-manager.writer-errors
Republisher
-
Subscription:
client-manager.republisher -
Retry mechanism for failed Writer messages
-
Maximum retry count: 5
-
After exhausting retries, publishes to
client-manager.writer-errors
Push Token Status Updater
-
Subscription:
client-manager.push-token-status(push) andclient-manager.web-push-token-status(web push) -
Updates push token validity status in PostgreSQL
-
Supports consuming from both push and web push subscriptions simultaneously via
-t bothflag -
Processes messages in batches (batch size: 100, interval: 1000ms)
Tenant Activator
-
Subscription:
client-manager.activate-customer -
Creates and initializes tenant schemas when new customers are activated
-
Uses
TenantSchemaManagerto create the schema and run tenant migrations
Account Deletion
-
Subscription:
client-manager.account-deletion -
Processes full account/customer deletion events
-
Drops the entire tenant schema for the customer
-
Uses
AuditLoggerfor compliance tracking
Contact Deletion Worker
-
Subscription:
client-manager.contact-deletion -
Processes individual contact deletion messages
-
Deletes device records for specific contacts from PostgreSQL
-
Errors published to
client-manager.contact-deletion-errors
Contact Deletion Job (Batch)
-
Scheduled batch job (no Pub/Sub subscription)
-
Queries BigQuery for contacts deleted across all active customers
-
Publishes deletion messages to
client-manager.contact-deletiontopic for processing by the Contact Deletion Worker -
Page size: 1M contacts per query
Orphan Deletion (Batch)
-
Scheduled batch job (no Pub/Sub subscription)
-
Deletes orphaned devices — devices with no associated contact that are older than a configurable threshold (default: 30 days)
-
Includes retry logic for failed customers
-
Supports a configurable customer exclusion list
Dashboard Collector (Batch)
-
Scheduled batch job (no Pub/Sub subscription)
-
Collects per-tenant metrics (device counts, sync validation, etc.)
-
Creates missing tenant schemas if needed
-
Writes results to
dashboard_tenant_metricsanddashboard_tenant_metrics_historytables -
For dashboard queries and views, see Client Manager Dashboard
Sequence Diagrams
Device Write with Retry
Shows the Writer and Republisher retry loop when writing device data fails transiently.
client-manager.writer participant W as Writer participant PG as PostgreSQL
tenant_
client-manager.republisher participant R as Republisher participant ERR as Pub/Sub
client-manager.writer-errors PS->>W: device registration event W->>PG: write device data alt success PG-->>W: OK W-->>PS: ack else transient error PG-->>W: error W->>RP: publish (retryCount=1) W-->>PS: ack RP->>R: deliver message R->>PG: retry write alt success PG-->>R: OK R-->>RP: ack else still failing (retryCount < 5) PG-->>R: error R->>RP: publish (retryCount++) R-->>RP: ack Note over R,RP: loop until success
or retryCount = 5 else retries exhausted (retryCount = 5) PG-->>R: error R->>ERR: publish to writer-errors R-->>RP: ack end else permanent error PG-->>W: error W->>ERR: publish to writer-errors W-->>PS: ack end
Contact Deletion Flow
Shows how the batch deletion job discovers deleted contacts and fans out to individual deletion workers.
(scheduled batch) participant BQ as BigQuery participant PS as Pub/Sub
client-manager.contact-deletion participant CDW as Contact Deletion Worker participant PG as PostgreSQL
tenant_
contact-deletion-errors JOB->>BQ: query deleted contacts
(all active customers) BQ-->>JOB: pages of deleted contacts (up to 1M per page) loop for each deleted contact JOB->>PS: publish deletion message
(customerId, contactId) end PS->>CDW: deliver deletion message CDW->>PG: DELETE devices
WHERE contact = contactId alt success PG-->>CDW: OK CDW-->>PS: ack else error PG-->>CDW: error CDW->>ERR: publish to contact-deletion-errors CDW-->>PS: ack end
Tenant Lifecycle
Shows tenant activation and account deletion as complementary operations.
activate-customer participant TA as Tenant Activator participant PG as PostgreSQL participant AD as Account Deletion participant DEL as Pub/Sub
account-deletion participant AUDIT as AuditLogger Note over ACT,PG: Tenant Activation ACT->>TA: new customer event TA->>PG: CREATE SCHEMA tenant_
Dependencies
-
PostgreSQL: Primary storage for all device data, organized in tenant schemas
-
BigQuery: Source for contact deletion data
-
Redis: Used for caching and coordination
-
Pub/Sub: Message transport for all event-driven sub-workers