Two rate-limit markers, per-user and per-tenant, must sit on one operation. What must the metadata type's declaration allow?
answer
- default is at most one
- the type declares repeatability
- a container holds the repeats
- the container is itself a marker
- two shapes from then on
basics
~20 sRepeatability, declared on the metadata type itself. By default one declaration may carry at most one attachment of a given metadata type; a repeatable type also names a container metadata type whose single member holds the repeats as a list.
solid answer
~50 sThe default rule is one attachment of a given metadata type per declaration, so two rate-limit markers on one operation is a compile error unless the type says otherwise. Repeatability is a property of the metadata type's declaration, not something an attachment site can opt into, and declaring it usually means naming a **container** metadata type whose one member is a list of the repeated attachments. The toolchain then wraps the repeats in that container. Two consequences follow. The declaration now has two shapes a reader can meet - one attachment, or a container of several - and readers written before the type became repeatable see only the shape they were written for. And the choice is a design decision: a repeatable marker and a single marker with a list-valued member express the same data, and the difference is readability against the cost of two shapes.
code
pseudocode · 12 linesmetadata type RateLimited repeatable into RateLimits
targets: method
member scope: text
member permitsPerSecond: number
mark RateLimited(scope = "user", permitsPerSecond = 10)
mark RateLimited(scope = "tenant", permitsPerSecond = 200)
function chargeCard(order)
...
// what the declaration now carries:
// RateLimits([ RateLimited("user", 10), RateLimited("tenant", 200) ])go deeper
Remember the default: a given metadata type goes on a given declaration at most once, and repeating it requires the type to have been declared repeatable.
Explain the machinery - repeats are wrapped into a container metadata type whose member is the list - and why that leaves the declaration with two possible shapes.
Weigh repetition against a single marker carrying a list, and flag the consequences you will live with: a second public type, order becoming meaningful, and a shape change that reaches existing readers.
Decide it once for the whole toolkit rather than per marker, so that every team writing policies meets the same shape and every reader in the platform is built for both.
## One attachment per declaration is the default Metadata systems start from a simple rule: a given metadata type may be attached to a given declaration **at most once**. It is a sensible default, because the common case is a marker that says one thing - this operation is limited, this field is injected - and a second attachment of the same type would immediately raise the question of which one wins. So the rate-limit case is a genuine conflict with the default. Two limits on one operation, one per user and one per tenant, is not an unusual requirement; it is what any real limiter needs. Something in the declaration has to change. ## Declaring repeatability Repeatability is declared **on the metadata type**, once, by its author. It is not a choice an attachment site can make, and no amount of supplying distinct member values makes a second attachment legal on a type that did not declare it. Concretely the declaration gains two things: - a statement that the type may appear more than once on one declaration; - the name of a **container** metadata type - a second metadata type whose single member is a list of the repeatable one. When the author writes two attachments, the toolchain replaces them with one attachment of the container holding both. That is the mechanism, and it explains every downstream oddity: repetition is not a new kind of attachment, it is ordinary single attachment of a type that happens to hold a list. ## The container is a metadata type like any other Because the container is itself a metadata type, it has its own declaration, its own target list, and its own name that shows up in tooling and in error messages. Its target list has to be at least as wide as the repeatable type's, or the container cannot legally sit where the repeats did. It also means the declaration now presents **two shapes**: | Attachments written | What the declaration carries | |---|---| | none | nothing | | one | one attachment of the repeatable type | | two or more | one attachment of the container, holding the list | A reader built for the single shape and a reader built for both shapes will disagree about a declaration carrying two markers, and that disagreement is silent. This is why repeatability is a decision to take **when the type is designed**, not a retrofit to reach for later: making a published type repeatable changes the shape that already-written readers meet. ## Repeatable marker, or one marker with a list member? The same data can be expressed either way, and interviewers like this comparison because it is a real design call: | | Repeatable marker | Single marker, list-valued member | |---|---|---| | Attachment site reads as | several independent statements | one statement with a collection inside | | Number of shapes a reader meets | two | one | | Per-entry members | natural - each repeat is a full attachment | needs a nested metadata type as the element | | Adding an entry later | attach one more line | edit the existing list | Repetition wins on the writing side: each line is a policy an engineer can read, comment on and remove independently. The list member wins on the reading side: exactly one shape, always. A shared toolkit usually wants the writing side to be pleasant, because far more people attach markers than write readers. ## What repetition costs 1. **A second named type in your public surface** - the container is visible, and it will appear in diagnostics. 2. **Two shapes forever.** Even after the whole codebase moves, the single-attachment shape stays legal. 3. **Order questions.** The container's list has an order, and the order is the order the attachments were written in; if your policies interact, you have just made source order semantically significant, and that should be a deliberate, documented choice rather than a discovery. 4. **A harder deprecation story.** Removing repeatability later is breaking for every declaration that used it.
- What has to be true of the container's own target list?It must permit at least every declaration kind the repeatable type permits. The container is an ordinary metadata type that ends up attached wherever the repeats were written, so a narrower target list would make a legal pair of attachments impossible to represent.
- When would you pick a list-valued member over making the type repeatable?When readers matter more than writers: one shape instead of two, no container type in the public surface, and no chance of a reader built for the single form meeting the plural one. It also fits when the entries are plain values rather than small structures with members of their own.
A form has a single line for an address. To record two, you do not squeeze both onto the line - you attach a sheet listing addresses, and that sheet is a different thing to look for than the line ever was.
saying these in an interview costs you the question
- Thinks the same metadata type may be attached twice by default
- Believes repeatability is chosen at the attachment site
- Says repeated attachments merge their member values into one
- Thinks the container is written by hand beside each repeat
- Assumes making a published type repeatable changes nothing for readers