Course outline · choose a lesson
Specify the ownership, trust, network and meaning at each boundary
Turn a system trace into boundary contracts with responsible owners, permission checks, approved routes and explicit domain meanings. Work through a misleading customer-ID join and a dependency schedule instead of treating arrows as guarantees.
28 MIN
By FDEInterviews · Updated
Transcript
An arrow on an architecture diagram needs a contract. Who owns changes on each side? What does the data mean? Which identity and permissions apply, and which network route is approved? Components still fail internally, through bad logic, exhausted resources or storage errors, so investigate them too, but boundaries add a risk of their own: mismatched assumptions between parts that each work fine.
Start with ownership. A source owned by another team can still support a correction API, a mapping layer or a joint repair, so ownership doesn't mean you can only wait. It means knowing who can authorize each change. Take a malformed identifier. You could normalize it under the contract, map it, quarantine it, reject the batch, or fix it at the source, and you choose by meaning and consequence. What you don't do is silently repair it because the join then succeeds. Record the original value, the rule and its version.
Next, meaning. In the page's synthetic freight example, billing's customer is the legal party paying an invoice. Dispatch's customer field identifies the delivery site. Both are small integers. And SQL will join any two integer columns without complaint, because the type system knows about integers and nothing about payers or sites.
The page runs this in SQLite. Join shipments straight to billing on the site ID, and shipment S1 goes to North Retail. Go through the site-to-payer mapping, and S1 belongs to South Wholesale. S2 flips the same way. Both queries return two rows, so a row count misses it. Worse, if a site has no mapping row at all, the inner join drops that shipment without a warning, while a left join keeps it, with an empty payer that someone can see.
Trust is more than identity. Authentication says who's calling. Authorization decides which objects and actions that identity may touch, and a broad service credential mustn't erase the end user's restrictions. So test at least four cases: an allowed user, a denied user, a revoked grant and a cache hit. A document hidden in the interface can still leak if its text reaches the model.
Connectivity is necessary, but it isn't permission. A call that works from your laptop doesn't show the deployed workload can make it, and a reachable route doesn't authorize sending customer data through it. If an external service is disallowed, a queue changes the timing. It doesn't make the route permitted. When a check fails, record which layer failed: DNS, connection, TLS, authentication, authorization or the application. They look alike and need different owners.
Last, the schedule. In a synthetic plan, a route review takes five working days, an identity review three, and implementation four, all starting together. Then an end-to-end check takes two. Earliest completion is the longest of the three plus two, so seven days. But if the identity review can't start until the route review finishes, it's five plus three plus two, which is ten. Record those assumptions, rather than reporting the biggest single number.
So write a boundary register, one row per important crossing, with the owner, meaning, identity, route, contract and evidence. An open row says the payer mapping history isn't supplied and the billing data owner will confirm it, and it doesn't say billing is the blocker. One names a dependency you can test. The other turns uncertainty into blame.
So every crossing gets a contract for ownership, meaning, trust and the network. Equal field types and row counts don't make equal meaning, and you plan from dependencies, not the single longest request. The full lesson is on fdeinterviews.com.
TL;DR: For each connection, state who owns changes, which identity and permissions apply, what network route is approved and what the data means. Boundaries deserve explicit checks, while failures inside components remain part of the investigation too.
Where you are. The previous lesson traced a record and marked evidence limits. Now turn the important crossings into contracts that can guide implementation, review and recovery.
An arrow needs a contract
Architecture diagrams can show ownership, trust and network boundaries well when their authors include them. A diagram of nothing but boxes may leave those questions open, and the remedy is to annotate or supplement it, not to assume every diagram hides the truth.
Components can fail internally through incorrect logic, resource exhaustion or storage errors, and boundaries add the risk of mismatched assumptions between parts that work fine on their own, so investigate both. The three boundary types below are useful views, not an exhaustive list of all failure modes.
Ownership defines coordination and correction rights
A source owned by another team may still support an approved correction API, a mapping layer or a joint repair. Ownership does not mean you can only wait; it means you need to know who can authorize each change and how the source and derived copies remain consistent.
For a malformed identifier, possible responses include a contract-approved normalization, explicit mapping, quarantine, rejection of the whole batch or source correction. Choose based on meaning and consequence. If malformed rows make the batch unsafe, continuing the rest may be wrong; if they are isolated and the contract permits partial processing, blocking all work may be unnecessary.
Record original values, transformation rule/version and reconciliation evidence where appropriate. Do not silently “repair” an identifier merely because a transformation lets the join succeed. Nor should you reject a valid canonicalization rule simply because it changes the source's formatting.
A shared word may hide different models
Martin Fowler's bounded-context explanation describes explicit boundaries within which a domain model is coherent, with mappings between models. A bounded context is not simply a synonym for a team ownership boundary or network segment.
In this synthetic freight example, billing's customer is the legal party paying an invoice, while dispatch's customer field identifies the delivery site. Both use small integers, and equal integers do not make equal entities. SQL will join any two integer columns without complaint, because the type system knows about integers and nothing about payers or sites; the meaning lives in the column names, and the join condition ignored them.
Run the SQLite fixture to see a query that is syntactically valid and semantically wrong:
import sqlite3
conn = sqlite3.connect(':memory:')
conn.executescript('''
CREATE TABLE billing_customer (payer_id INTEGER PRIMARY KEY, name TEXT);
CREATE TABLE delivery_site (site_id INTEGER PRIMARY KEY, payer_id INTEGER, name TEXT);
CREATE TABLE shipment (shipment_id TEXT PRIMARY KEY, site_id INTEGER);
INSERT INTO billing_customer VALUES (1, 'North Retail'), (2, 'South Wholesale');
INSERT INTO delivery_site VALUES (1, 2, 'Harbor depot'), (2, 1, 'Hill depot');
INSERT INTO shipment VALUES ('S1', 1), ('S2', 2);
''')
wrong = conn.execute('''
SELECT s.shipment_id, b.name
FROM shipment s JOIN billing_customer b ON b.payer_id = s.site_id
ORDER BY s.shipment_id
''').fetchall()
correct = conn.execute('''
SELECT s.shipment_id, b.name
FROM shipment s
JOIN delivery_site d ON d.site_id = s.site_id
JOIN billing_customer b ON b.payer_id = d.payer_id
ORDER BY s.shipment_id
''').fetchall()
print('same-shaped IDs:', wrong)
print('explicit mapping:', correct)
assert correct == [('S1', 'South Wholesale'), ('S2', 'North Retail')]
# same-shaped IDs: [('S1', 'North Retail'), ('S2', 'South Wholesale')]
# explicit mapping: [('S1', 'South Wholesale'), ('S2', 'North Retail')]
Both queries return two rows, so a row-count check alone misses the error. The mapping in this fixture is supplied domain evidence; in a real system, verify its owner, current validity, tenant scope and change history. Nor does the example establish that every site has exactly one payer forever. The same shape hides a second failure, too. If a shipment's site has no mapping row at all, the inner join returns nothing for it and the shipment disappears from the report without a warning. Left joins at both steps keep it, with an empty payer beside it, so the gap is a row someone can see and the row count still reconciles; a left join on the first step alone still loses the shipment at the second join.
Trust concerns permissions as well as identity
Authentication identifies the caller or service; authorization decides which objects and actions that identity may access. A broad service credential must not erase the end user's restrictions when returning results.
For retrieval, enforce the applicable permissions before unauthorized content reaches model context or the response. Ingestion filters, tenant-specific indexes and current query-time checks may work together; the right design depends on access changes and the serving paths. “Query time instead of ingestion” is an incomplete rule when caches, embeddings, direct fetches and revoked grants also need controls.
Trace the grant source and its freshness, and test at least an allowed user, a denied user, a revoked grant and a cache hit. A document hidden in the UI can still leak if its text reaches the model or a downloadable endpoint, so keep authorization outside model-generated claims.
Network connectivity is necessary but not permission
Describe the source, destination, port/protocol, DNS, proxy, TLS requirements, credentials and approval owner. A successful call from a laptop does not show that the deployed workload can make it, and a route being technically reachable does not authorize sending customer data through it.
If an external service is unavailable or disallowed, a queue can decouple timing but cannot make the route permitted. A cache can reduce calls but brings its own storage, staleness and access questions. An approved local alternative or a different workflow may be needed. Do not propose queueing forever as a solution to a permanently prohibited destination.
Use bounded checks from the intended environment under the actual network process. Record whether a failure was DNS, connection, TLS, authentication, authorization or application behavior, because these layers produce similar symptoms and need different owners and repairs.
The dependency path, calculated
The slowest request is not automatically the whole project timeline: some prerequisites run in parallel, while integration verification may start only after several finish.
In this synthetic plan, a route review takes five working days, an identity review three and implementation four, and all three can start together with separately assigned capacity. The end-to-end check needs both approvals and the implementation, then takes two days. Earliest completion is max(5, 3, 4) + 2 = 7 working days under those assumptions.
If identity review cannot start until the route review finishes, the path becomes 5 + 3 + 2 = 10 days, assuming implementation still finishes in parallel. If the same engineer must implement and also do another task, capacity may change the schedule again. Record dependency and staffing assumptions rather than reporting the largest single number as the answer.
The boundary register
For the freight path, use one row per important crossing: producer and consumer, data meaning, current owner, permitted identity/action, route, contract/version, failure behavior and evidence status. Link the source of each decision.
A useful unresolved row says “payer mapping history not supplied; billing data owner to confirm changes before historical reporting.” It does not say “billing is the blocker,” because the first names a testable dependency and the second turns uncertainty into blame.
The spine above is one row of the boundary register, drawn as the order you fill it in, from the two ends of the arrow to the evidence behind every claim on it.
Do this before moving on
Run the join fixture, change the site-to-payer mappings and verify that the explicit join follows them. Try crossed mappings and mappings where each payer ID happens to equal its site ID: the same-shaped-ID join ignores the mapping, so it can return the right answer by coincidence and still be the wrong rule. Add a missing site mapping and decide how the real workflow should expose that unresolved shipment; an inner join silently omits it, so a reconciliation count or left joins at both steps may be required.
Write three negative checks for the trust boundary, including revoked access and a cached response. For a proposed external route, state both the connectivity and the data-use prerequisites, and explain why adding a queue waives neither.
Finally, calculate the seven-day and ten-day dependency plans and identify the assumptions that distinguish them. Your boundary register passes when it names decisions, contracts and evidence instead of relying on a box label or a handshake in the architecture diagram.
Go deeper
- Multi-tenancy isolation is the trust boundary treated as an architectural requirement.
- VPC deployment is what the network boundary looks like when you have to deploy inside it.
- PII handling covers what changes the moment data crosses an ownership boundary into your system.
- Data quality is the discipline for data you cannot fix at source.
- Permissions-aware retrieval over ten million documents is the trust boundary as an interview question, and it is a common filter.
- The reference architecture is the checklist of layers and trust boundaries to walk while you look.
Key takeaways
- Boundaries require contracts for responsibility, meaning, permissions and connectivity.
- An ownership boundary permits coordinated repair; it does not justify silent transformation or automatic partial processing.
- Equal field types and row counts do not establish equivalent domain meaning.
- Apply permission controls across all serving paths, including caches and current grants.
- Plan from dependencies and capacity, not only the longest individual request.
Check yourself
Answer before you look. Recalling it is what makes it stick; recognising it does not.
1Both joins return two rows. Does that establish the payer attribution is correct?
2An external endpoint is prohibited. Does putting requests in a queue make the integration acceptable?
3Parallel tasks take five, three and four days, followed by two days of checking. What is the earliest completion under the supplied independent-capacity assumption?
Sign in free to save your progress and return to this lesson.
