When designing a screen's address, what do the path, the query string and the fragment each carry?
answer
- three regions, three jobs
- identity versus view of that identity
- optional and unordered wants the query
- the fragment never reaches the server
- not transmitted is not the same as private
basics
~20 sThe path carries identity - which screen and which entity. The query string carries refinements of that identity, such as search, filters, sort and page. The fragment carries client-only position or state and is never sent to the server.
solid answer
~50 sI treat the three as carriers with different jobs. The **path** says what the screen *is*: the section of the application and the identifier of the entity it is about, one canonical spelling per thing, hierarchical so parents read from left to right. The **query string** says how that same thing is being *looked at*: an unordered set of optional key-value pairs - search term, filters, sort, page - where a key may repeat for a multi-select and where leaving a key out means "the default". The **fragment** is the part after the `#`, and the distinguishing fact is that the browser never puts it in the request, so it suits an in-page position or a purely client-side detail you would rather keep out of server logs. The rule of thumb: if it changes *which* thing, it is path; if it changes the *view of* that thing, it is query.
go deeper
Learn the split: the path says which screen and which item, the query says how it is filtered or sorted, and the part after the hash is the in-page position. Pointing at a real address and naming each region is enough at this stage.
Explain the properties that drive the choice - path segments are required and ordered, query keys are optional and unordered and may repeat, the fragment is not transmitted - and apply them to a value the interviewer names.
Show what each choice commits you to in production: route-table size, comparable links and analytics aggregation, what lands in access logs, and normalising parameter order before an address is used as a key.
Argue it as an interface the organisation maintains. Address shape constrains caching, observability and support workflows, and old links in other people's messages make parameter names hard to change later.
## Three carriers in one address An address is not one undifferentiated string. `/reports/42/lines?status=open&sort=-due&page=3#row-118` has three regions, and each one means something different to users, to caches, and to the server that serves the document. Choosing the wrong region is one of the most durable mistakes in an application, because links outlive the code. ## The path: identity and hierarchy The path answers **what is this screen about**. It reads as a hierarchy from left to right, so containment is visible: a section, then a collection, then the identifier of one entity, then a sub-view of that entity. Properties that follow from putting a value here: - **Canonical.** Each thing gets one address, which makes links comparable and analytics aggregatable. - **Required and ordered.** A segment cannot be omitted without changing which address this is, so optional values sit badly here. - **Human-facing.** It is the part users read in the link, quote in a ticket and recognise in history. - **Few shapes.** A handful of path templates cover the whole application, which is what keeps a route table small. ## The query string: refinement of a fixed identity The query string answers **how is the user looking at it**. It is an unordered bag of key-value pairs, each optional, and it does not change *which* entity or screen is addressed. - Optionality is natural: absent means default, so the bare path stays a valid address. - A key may appear more than once, which is the standard way to carry a multi-select without inventing a delimiter. - Order carries no meaning, so two addresses differing only in parameter order denote the same screen - worth normalising if you use the address as a key. - It is sent to the server, so it lands in access logs exactly as the path does. Typical residents: a free-text search term, facet filters, sort field and direction, page or cursor, a date range, a display mode. ## The fragment: client-only The fragment is everything after the first `#`. Its defining property is that **the browser strips it from the request**: the server never sees it. Historically it names an in-document anchor and the browser scrolls to the matching element; it is also a natural home for state that is genuinely about the reader's position, and for detail you would rather not have written into a proxy's log file. It is still copied with the link and still kept in history, so it is not a hiding place for secrets - only a place the server does not learn about. ## Side by side | Carrier | Sent to server | Optional | Ordered | Typical content | |---|---|---|---|---| | Path | yes | no | yes, hierarchical | section, collection, entity identifier, sub-view | | Query | yes | yes | no | search, filters, sort, page, display mode | | Fragment | no | yes | not applicable | in-page anchor or scroll target, client-only detail | ## Deciding where a value goes 1. **Does it change which thing the screen is about?** Yes - path. A different identifier is a different screen, not a variation of one. 2. **Is it optional, and is the address still valid without it?** Yes - query. Filters and sort come and go while the screen stays the same screen. 3. **Can several of them be set independently at once?** Query, because paths would force one segment order and empty placeholders for the unset ones. 4. **Is it only about where in the rendered document the reader is?** Fragment, and accept that the server is unaware of it. ## The mistakes this distinction prevents - **Filters promoted into the path**, producing a combinatorial set of route templates and addresses like `/reports/open/due/3` where each segment's meaning depends on the ones around it. - **Identity demoted into the query**, so one screen has many spellings, links are not comparable, and the route table cannot express which parent a screen belongs to. - **Treating the fragment as private.** It is not transmitted, but it is copied, bookmarked and stored in history, so it guards against log retention only. - **Assuming parameter order is meaningful**, which quietly breaks any cache or deduplication keyed on the raw address. A router matches the path, hands the screen the identifiers it found there, and exposes the query as a parsed bag of values; the fragment usually reaches the application only as a value it can read for itself. The shapes differ between products, but the division of labour between the three regions is a property of addresses, not of any one framework.
- Two addresses differ only in the order of their query parameters. Are they the same screen?To the application, yes - the query is an unordered set, so both parse to the same state and render the same view. To anything that keys on the raw string, such as a client-side response cache or a metrics dimension, they are two different keys. That is why serialization should emit parameters in a fixed order.
- Why not put a secret in the fragment, given the server never receives it?Because the server is not the only threat. The fragment travels with the copied link, sits in browser history and bookmarks, and is readable by any code running on the page. Withholding it from access logs removes one exposure of several, which is not enough for anything whose disclosure matters.
- When would a value legitimately appear in both the path and the query?Rarely, and it should be one or the other. The near-case is a human-readable slug in the path alongside a stable identifier - then one of the two is authoritative and the other is decoration, and the screen resolves conflicts by trusting the authoritative one.
saying these in an interview costs you the question
- Putting optional filters into path segments and inventing placeholder values
- Addressing the same entity through several query spellings instead of one path
- Calling the fragment private or secure because the server never receives it
- Assuming query parameter order is significant to the application
- Believing a multi-select needs a custom delimiter rather than a repeated key