A service composes its database password into one connection string at start-up — what does that composite cost at replacement time?
answer
- one value becomes a field in a blob
- fixed at the moment it is composed
- every object built from it holds a copy
- composite inherits the least sensitive part
- supply per connection instead
basics
~20 sReplacement becomes a rebuild rather than an assignment: the string is fixed at the moment it is composed, and every pool, client and retry path constructed from it holds its own copy of the old password until each one is remade.
solid answer
~40 sComposing a credential into a connection descriptor turns a value you hold separately into a field inside an opaque composite. Two costs follow. First, **replacement is a rebuild**: the string cannot be edited in place inside the objects that already hold it, so picking up a new password means recomposing the string and recycling the pool and clients built from it. Second, the composite is **copied freely**, because most of it — host, port, database name — is unremarkable, so it spreads into retry paths, health checks and secondary clients, each now an independent holder of the password. The shape that avoids both is a client that calls a supplier for the credential each time it opens a connection, so the next connection picks up whatever value is held now.
code
pseudocode · 12 lines// composed once: the credential is frozen inside an opaque descriptor
descriptor = "host=" + host + ";port=" + port + ";user=" + user
+ ";password=" + heldCredential
pool = openPool(descriptor)
reportingClient = openClient(descriptor) // a second holder of the same old value
// replacing heldCredential now changes nothing for pool or reportingClient
// supplied per connection: the credential is never baked into a stored string
pool = openPool(host, port, user, credentialSupplier = fn() -> heldCredential)
// each NEW connection calls the supplier and gets whatever is held now;
// connections already open keep the value they were opened with
pool.retireIdleConnections() // still needed to move the old onesgo deeper
Recall that a password concatenated into a connection descriptor is fixed at that moment; changing the credential afterwards does not change the string that was already built.
Explain the two consequences — replacement becomes a rebuild of everything constructed from the composite, and the composite spreads because it looks like ordinary configuration.
Show the design move: keep the credential separate and let the client call a supplier per connection, while still recycling connections opened with the earlier value.
Treat it as a library-shape standard across services, so that how many holders of a credential a process contains is a property of the platform rather than of each team's start-up code.
## What composition does to a credential At start-up the service resolves a password and then concatenates it with host, port, user and database name into a single descriptor, which it hands to a pool. From that moment the credential has stopped being a value the service holds and started being a **field inside a composite that other objects hold**. Nothing about the password changed; what changed is who owns it and how many of them there are. ## The costs, in order of how often they bite 1. **Replacement becomes a rebuild.** The composite was built once. There is no field to assign — picking up a new password means recomposing the whole descriptor and then recycling everything that was constructed from the previous one. A reload that updates the service's own credential variable and leaves the composed string alone is a no-op, and it is a convincing one, because the variable does now hold the new value. 2. **The composite multiplies.** It is convenient and it looks like configuration, so it is passed into a second client for reporting queries, into a retry path, into a health check, into a migration step at start-up. Each of those is now an independent holder of the old password with its own lifetime, and a replacement has to reach all of them. 3. **It is handled at the sensitivity of its least sensitive part.** Host, port and database name are the sort of thing that gets pasted into a ticket or typed into a dashboard field without a second thought. A descriptor that mostly looks like addressing information inherits that habit, even though one of its fields is a password. ## The shape that avoids it The alternative is to keep the credential a separate value and let the client ask for it at the moment it needs it. Instead of handing the pool a finished string, hand it the stable parts plus a **supplier** — a small function that returns whatever credential the service currently holds. Each new connection calls the supplier, so a replaced value is picked up by the next connection without reconstructing anything. | | where the credential lives | picking up a replacement | number of holders | |---|---|---|---| | composed once into a descriptor | inside every object built from that string | recompose, rebuild the pool, retire connections | one per copy of the composite | | supplied per connection | in one place the supplier reads | the next connection uses the current value | one | Note what the second row does **not** buy: connections already open were authenticated with the earlier value and keep working until they are retired. The supplier fixes which value new connections use, not which value old connections used. That is why a deliberate recycle still belongs in the reload path. ## When one string is the only option Some clients genuinely accept nothing else. Then the discipline is narrow and worth stating: - compose the descriptor in exactly **one** function, from a credential the service also holds separately, so there is one place to change and one place to review; - never pass the composite to anything that could have been given host and port instead; - make the reload path recompose the descriptor **and** recycle the pool, not just recompose it; - keep the composed string out of anything that treats its argument as ordinary configuration, because the composite is plain text to whoever holds it — wrapping a password in a longer string hides nothing. ## Why this is worth an interview minute It looks like a style question and it is really a question about how many copies of a credential a process contains and who owns each one. A service that holds the password in one place and composes on demand has one holder and a replacement it can reason about. A service that composed once at start-up has as many holders as it has objects, no inventory of them, and a reload that appears to work. The second is far more common, and the candidate who can describe the difference in terms of holders rather than tidiness is the one who has actually had to replace a credential in a running system.
- The client library accepts only a single connection string. What is the best you can do?Build the string in exactly one function, from a credential you also hold separately, and make the reload path recompose it and recycle the pool. One builder means one place to change and one place to review. What makes replacement unbounded is copies of the composite scattered through retry paths, health checks and secondary clients.
- Why does a composed descriptor tend to be handled less carefully than the password inside it?Because most of its fields are not sensitive. Host, port and database name are the kind of detail people move around without thinking, and the composite inherits that handling even though one field is a credential. A value ends up treated at the sensitivity of its least sensitive part.
saying these in an interview costs you the question
- Thinks editing the service's credential variable updates the composed string
- Treats the composite as harmless because it mostly contains addressing detail
- Believes wrapping the password in a longer string obscures it
- Copies the same composite into retry paths and health checks
- Assumes a per-connection supplier also fixes connections already open