ADR-003: Mailing Address Schema Design
Status
Accepted
Context
The identity service integrates with twoCircles as the identity provider, which stores address data in a generic line-based format:
line1: Street nameline2: House numberline3: Addition (e.g. "A")
We needed to decide how to model the mailing address in our GraphQL schema, specifically whether to mirror twoCircles' generic line format or use semantically named fields.
Option A: Generic line fields (Stripe/Shopify pattern)
input MailingAddressInput {
line1: String
line2: String
line3: String
city: String
postalCode: String
countryCode: CountryCode
}Maps 1:1 to twoCircles. Used by Stripe and other large public APIs as the lowest common denominator for international addresses.
Option B: Structured fields
input MailingAddressInput {
street: String
houseNumber: String
houseNumberSuffix: String
city: String
postalCode: String
countryCode: CountryCode
}Semantically named fields that map to twoCircles' format in the identity service mapper layer.
Decision
We adopt structured fields (Option B).
Rationale
1. Private API with a single controlled consumer
The generic line format is the right default for public APIs with unknown consumers (e.g. Stripe). Our GraphQL API is private with a single consumer: the React Native app. Optimizing for that consumer's developer experience is the correct trade-off.
2. No parsing required in React Native
With structured fields, each field maps directly to a form input. With generic line fields, the app would need to know that line1=street, line2=houseNumber, line3=houseNumberSuffix to render meaningful form inputs — moving the twoCircles coupling into the client.
3. Coupling is isolated to the mapper
The twoCircles-specific mapping (street → line1, houseNumber → line2, houseNumberSuffix → line3) lives exclusively in the identity service's mapper. If twoCircles changes their format, only the mapper needs to change — not the schema or the app.
4. houseNumberSuffix over addition
The field is named houseNumberSuffix rather than addition (a direct translation of the Dutch "toevoeging") because it is self-documenting in English and makes clear it is a suffix to the house number, consistent with the NEN 5825 Dutch addressing standard.
Consequences
Positive
- Clear form mapping: React Native renders fields without any decoding logic
- Single source of truth: twoCircles coupling is isolated to the identity service mapper
- Readable schema: Field names are self-documenting for any consumer
Negative
- Dutch-centric structure:
houseNumberandhouseNumberSuffixare concepts that don't exist in all address systems (e.g. US, UK)
Risks
- International addresses: If we ever need to support non-Dutch address formats, the structured fields may not map cleanly. Mitigation: All address fields are optional, so
streetcan serve as a free-text catch-all for countries that don't use a separate house number. If a more complex international format is required, a separateInternationalMailingAddressInputtype can be introduced without breaking existing logic or clients.