Skip to content
← All patterns

user-data

Account & Settings

What are this account’s preferences?

Two entity types under one key, told apart by the sort key.

A user's account record and their settings always travel together, so they share a partition and are separated by a sort-key label rather than living in two tables. One Query returns both; a GetItem still fetches either on its own.

The model

Account

The account record: who the user is.

pk
USER#<userId>
sk
ACCOUNT

Attributes: email (S), displayName (S), createdAt (N)

Settings

The user's preferences, read on almost every page.

pk
USER#<userId>
sk
SETTINGS

Attributes: theme (S), locale (S), emailDigest (S)

Access patterns

  • QueryLoad an account with its settings

    Both records for a user, in one read.

  • GetItemLoad an account

    Just the account record.

Design notes

The sort key is a label, not a sequencewhy

ACCOUNT and SETTINGS are not ordered, they are named. Compare Feature Flags, where one partition holds many items of a single type and the sort key picks which one; here a partition holds one item of each of two types, and the sort key says what each is. That distinction - many-of-one versus one-of-each - is the idea every later model builds on.

Co-located because they are read togetherwhy

Splitting settings into their own table would mean two round trips on every page that needs both. They share a partition because the access pattern pairs them, not because they are conceptually similar.

The over-fetch is not where you would expecttrade-off

Reading both items rather than one costs no extra read capacity here: capacity is charged in 4 KB blocks, and an account plus its settings sit well inside one. What the extra item does cost is bytes on the wire and work in the caller. The habit worth keeping is the one that pays at scale - fetch what the caller uses - but the meter beside this table will not reward it on rows this small, and pretending otherwise teaches a rule the numbers contradict.

Taught in the course

account-settingsDynamoDB workbench
Ready to run
Explore an access patternSelect to load & run

Both records for a user, in one read.

Request
Execute against the local Dynoxide engine
ReturnedFiltered outChanged
PK(pk)
SK(sk)
createdAt
displayName
email
emailDigest
locale
theme
USER#u-ada
ACCOUNTS
1753747200N
AdaS
ada@example.comS
—
—
—
USER#u-ada
SETTINGSS
—
—
—
weeklyS
en-GBS
darkS
USER#u-raj
ACCOUNTS
1774483200N
RajS
raj@example.comS
—
—
—
USER#u-raj
SETTINGSS
—
—
—
offS
en-GBS
lightS
USER#u-mei
ACCOUNTS
1787443200N
MeiS
mei@example.comS
—
—
—
USER#u-mei
SETTINGSS
—
—
—
dailyS
zh-CNS
systemS
Awaiting request
Your next query starts here.

Choose an access pattern above, or build your own request. See what comes back and what it costs.

Write transactions, streams, tags and TTL are among the operations this browser build leaves out. dynoxide's native build has them.