Chapter 18: Customer Accounts and Profiles
Why This Exists
E-commerce businesses do not survive on one-time buyers; they survive on Customer Lifetime Value (LTV). If a customer has to manually type their home address and credit card number every time they want to buy a shirt, they will abandon the cart. Customer Accounts exist to reduce checkout friction, store historical data (order history, wishlists), and enable personalized marketing and loyalty programs.
Real World Problem
A customer creates an account and saves their shipping address as "123 Old St." They place five orders over two years.
They move to "456 New St," log into their profile, and update their saved address.
Because the database was designed poorly, the developer linked the historical orders table directly to the customer.address column. Suddenly, the system retroactively changes the shipping address on the five old orders. When the finance team runs an audit on shipping taxes collected per state, the historical data is completely corrupted.
Everyday Analogy
Think of a local coffee shop.
- Guest Checkout: Walking in for the first time. The barista asks for your name and your order.
- Customer Profile: You are a "regular." You walk in, the barista greets you by name, asks if you want "the usual," and knows you have a punch card for a free coffee. The transaction takes 5 seconds instead of 30.
Beginner Explanation
A Customer Profile is the "My Account" page on a website. It remembers everything about you:
- Your name and email.
- Where you live (Address Book).
- How you pay (Saved Cards).
- What you bought in the past (Order History). This makes buying things faster and allows the store to send you targeted emails (like a discount code on your birthday).
Intermediate Explanation
Architecturally, Customer data must be heavily normalized. A customer does not have an address; a customer has a collection of addresses (Home, Work, Mom's House). A customer does not have a credit card; they have a collection of payment tokens.
Furthermore, there is a strict separation between Master Data (the current state of the customer) and Transactional Data (the historical state of an order). When an order is placed, the checkout system must take a snapshot of the address and store it permanently inside the order record. It must never rely on a foreign key pointing to the user's active address book.
Advanced Explanation
At the enterprise level, Customer Profiles evolve into a CDP (Customer Data Platform). A CDP aggregates the "360-Degree View" of the customer across multiple systems:
- The E-commerce database (Online orders).
- The Point-of-Sale (POS) system (In-store physical purchases).
- The Email Marketing system (Did they open the newsletter?).
- The Customer Support system (Zendesk tickets).
This centralized data lake powers AI recommendation engines. If the CDP knows the user bought a coffee machine in-store and opened an email about espresso beans, the website homepage dynamically changes to feature coffee grinders when they log in.
Real World Example
Sephora's Beauty Insider: Sephora's customer profiles go far beyond shipping addresses. They collect data on skin type, hair color, and preferred brands. This profile data is deeply integrated into their catalog search engine. When a logged-in user searches for "foundation," the architecture boosts products that match their saved skin type to the top of the results, drastically increasing conversion rates.
Architecture Design
Here is how a unified Customer Service aggregates profile data:
graph TD
UI[My Account Page] --> API[Customer Profile Service]
API -->|Reads Core Data| DB_Cust[(Customer DB)]
API -->|Reads Addresses| DB_Addr[(Address Book DB)]
API -->|Fetches History| OMS[Order Management Service]
API -->|Fetches Saved Cards| Pay[Payment Gateway - Stripe]
API -->|Fetches Points| Loyalty[Loyalty & Rewards Service]
Database Design
Notice how the addresses table allows multiple entries, with one marked as default.
CREATE TABLE customers (
id UUID PRIMARY KEY,
auth_user_id UUID, -- Links to the Authentication system
first_name VARCHAR(100),
last_name VARCHAR(100),
phone VARCHAR(20),
created_at TIMESTAMP
);
CREATE TABLE addresses (
id UUID PRIMARY KEY,
customer_id UUID,
address_line_1 VARCHAR(255),
city VARCHAR(100),
state VARCHAR(50),
zip_code VARCHAR(20),
is_default_shipping BOOLEAN,
is_default_billing BOOLEAN,
FOREIGN KEY (customer_id) REFERENCES customers(id)
);
CREATE TABLE saved_payment_methods (
id UUID PRIMARY KEY,
customer_id UUID,
gateway_token VARCHAR(100), -- e.g., 'cus_xyz123' from Stripe
card_brand VARCHAR(20),
last_4 VARCHAR(4)
);
API Design
RESTful endpoints for profile management:
GET /api/customers/me(Returns core info, default address, and masked payment methods)POST /api/customers/me/addresses(Add a new address to the book)PUT /api/customers/me/addresses/{id}/default(Set as primary)
Production Considerations
- Guest to Registered Conversion: A user buys as a Guest. Two weeks later, they create an account using the same email. The system must run a background job:
UPDATE orders SET customer_id = X WHERE email = Y. This instantly populates their new account with their historical "Guest" orders, delighting the user. - GDPR and CCPA (Data Privacy): Laws like the "Right to be Forgotten" require you to delete a user's PII (Name, Address) upon request. However, financial laws require you to keep transaction records for 7 years. You must build scripts that anonymize the customer profile (changing "John Doe" to "Deleted User") while leaving the financial totals intact on the
orderstable.
Security Considerations
- Account Takeover (ATO): If a hacker steals a password, they can log in, buy a laptop using the user's saved credit card, and ship it to a new address. High-security systems require re-authentication (or CVV confirmation) when adding a new shipping address or spending over a certain threshold with a saved card.
Common Mistakes
- Foreign Keys for Order Addresses: Doing this:
SELECT * FROM orders JOIN addresses ON orders.address_id = addresses.id. If the user updates or deletes their profile address, the order history breaks. Orders must store a hardcoded snapshot of the address text at the moment of checkout. - Storing Full Credit Cards: Storing the 16-digit card number in the database to allow "saved card" checkouts. This violates PCI-DSS. You must use Stripe's Customer tokens to save cards.
Tradeoffs and Alternatives
- Forced Registration vs. Guest Checkout: Forcing users to create an account before buying gives you 100% perfect customer data, but kills conversion rates (some users will just leave). Offering Guest Checkout maximizes sales but results in fragmented data (a user might use three different email variations over a year, looking like three different customers to the analytics team).
Interview Questions
- Why must an Order record store a snapshot of a shipping address rather than a foreign key linking to the Customer's Address Book?
- How do you design an API to handle a scenario where a user wants to check out using a credit card they saved three months ago?
- How do you balance the GDPR requirement to "Delete User Data" with the IRS requirement to "Keep Financial Records"?
Hands-On Exercise
- Design a JSON payload for a
GET /customers/meresponse. - Ensure it includes their basic info, an array of addresses (identifying the default), and an array of saved payment methods (showing only the last 4 digits and brand).
- Do not include their full order history in this payload (explain why fetching the entire order history on the profile load is an anti-pattern).
Key Takeaways
- Customer Profiles exist to reduce checkout friction and enable personalization.
- Master Data (Address Book) must be strictly separated from Transactional Data (Order Snapshots).
- Customer data is heavily regulated (GDPR/CCPA); architectures must support data anonymization and export.
- Storing credit cards requires Tokenization via a payment gateway.
Further Reading
- GDPR Compliance for Software Engineers
- Stripe API: Saving Cards for Future Payments