customer-service is a Quarkus service that owns shopper profile data, addresses, shopper groups, and GDPR request handling. Storage is PostgreSQL with store_id as a discriminator column for multi-tenant isolation.
This service is distinct from identity-service. identity-service owns authentication, credential verification, and JWT issuance. customer-service owns everything that describes a customer as a person and a commercial entity within a store.
Customer Model#
customers#
customers is the root table for all shopper records.
| Column | Notes |
|---|---|
customer_id UUID PK | |
store_id | Discriminator |
email | |
first_name | |
last_name | |
phone | Nullable |
locale | Preferred locale for communications |
created_at | |
anonymized_at | NULL while active; set on GDPR erasure |
customer_addresses#
customer_addresses stores one or more postal addresses per customer. Columns: address_id PK, customer_id FK, store_id, standard address fields (lines, city, state, country, postal code), is_default_shipping BOOLEAN, is_default_billing BOOLEAN.
Shopper Groups#
Shopper groups are the primary mechanism for segmenting customers into commercial tiers. They drive price list assignment, content visibility, shipping eligibility, and promotion conditions.
shopper_groups#
shopper_groups defines the available groups per store. Columns: group_id PK, store_id, name (e.g. Retail, Wholesale, VIP), price_list_id FK — a direct reference to a price list in catalog-service’s schema. The linked price list is the one members of this group receive at cart and checkout.
customer_group_memberships#
customer_group_memberships is the junction table: customer_id, group_id, store_id, assigned_at, assigned_by. A customer can belong to more than one group.
Downstream uses of shopper groups#
| Consumer | Use |
|---|---|
| cart-service | Calls GetCustomerGroups to resolve the customer’s price_list_id before fetching prices from catalog-service |
| storefront-engine | Content visibility rules can target specific groups |
| shipping-service | Shipping method eligibility can be restricted by group |
| marketing-service | Promotion conditions can require membership of a specific group (customer_group_in condition) |
GDPR#
All four data subject rights are supported. Requests are tracked in gdpr_requests:
| Column | Notes |
|---|---|
request_id UUID PK | |
customer_id FK | |
store_id | |
type | ACCESS / ERASURE / RECTIFICATION / PORTABILITY |
status | PENDING / IN_PROGRESS / COMPLETED |
created_at | |
completed_at | Nullable |
Right of Access (Subject Access Request)#
customer-service collects its own data in full. Cross-service data — orders, payment records, communication logs — is collected via gRPC calls to the respective services. The compiled result is returned as a structured JSON export.
Right to Erasure (Right to be Forgotten)#
customer-service nulls out all PII fields (name, email, phone, addresses) on the customers and customer_addresses records and sets anonymized_at. It then publishes customer.erasure_requested to Kafka. All other services that hold PII for this customer — communication-service, payment-service, order-service — consume this event and anonymize their own records independently.
The customer record itself is retained for order history and financial integrity. Only the identifying fields are removed.
Right to Rectification#
Profile fields are updated directly. No special multi-service orchestration is required.
Right to Data Portability#
Follows the same collection flow as the right of access but formats the output as a machine-readable JSON download.
gRPC Interface#
These methods are exposed to internal callers only.
| Method | Called By | Purpose |
|---|---|---|
GetCustomerGroups(customerId, storeId) | cart-service | Returns the customer’s group memberships so the caller can resolve price_list_id |
GetCustomerSnapshot(customerId, storeId) | checkout-service | Returns name, email, locale, and default addresses for order creation |
GraphQL Subgraph#
customer-service participates in Apollo Router federation as a subgraph. Access is restricted to authenticated customers — each query operates on the requester’s own account.
Types#
Customer — Fields: id, email, firstName, lastName, phone, locale, addresses, orders (federated from order-service), shopperGroups.
Queries#
| Query | Notes |
|---|---|
me | Returns the authenticated customer’s own profile and addresses |
Mutations#
| Mutation | Notes |
|---|---|
updateProfile | Update name, phone, locale |
addAddress | Add a new address to the customer’s address book |
updateAddress | Modify an existing address |
deleteAddress | Remove an address |
requestErasure | Initiate a GDPR erasure request |
Kafka Consumed#
customer-service is primarily an event source. It does not consume domain events from other services during normal operation.
Kafka Events Published#
| Topic | Trigger |
|---|---|
customer.created | New account registration |
customer.updated | Profile field change |
customer.group_assigned | Customer added to a shopper group |
customer.group_removed | Customer removed from a shopper group |
customer.erasure_requested | GDPR erasure initiated; triggers cross-service PII anonymization |
customer.erased | Final confirmation after all services have responded to the erasure request |
Vault Configuration#
| Key path | Purpose |
|---|---|
ss3/kv/customer-service/db.url | PostgreSQL JDBC URL |
ss3/kv/customer-service/db.username | Database username |
ss3/kv/customer-service/db.password | Database password |
ss3/kv/shared/ | Shared Kafka bootstrap and OTel config |