In the Valet Key cloud design pattern, a client wants to upload a large file directly to object storage (like Amazon S3 or Azure Blob Storage) instead of routing the bytes through your application server. What does the application server give the client to make this possible, and what two properties does that credential typically have?
answer
- valet key = temporary car key
- bearer token, not identity
- scope + expiry, not one or the other
- app server signs, never touches bytes
basics
~20 sThe server hands the client a special temporary link (like a pre-signed URL) that lets it talk straight to the storage service. That link only works for a short time and only for one specific action, like uploading one file.
solid answer
~30 sThe app server generates a pre-signed URL (or SAS token on Azure) using its storage credentials, scoped to one object/action (e.g., PUT to a specific key) and stamped with a short expiry. The client uses that URL to talk directly to blob storage, bypassing the app tier for the actual data transfer. Two defining properties: scope (limited to one resource/verb, not the whole bucket) and time-limited validity (expires in minutes to hours). This keeps the app server's long-lived credentials off the wire and out of client hands.
go deeper
Should be able to say the client uploads directly using a temporary signed link and that it expires, even without naming the exact crypto mechanism.
Should name pre-signed URL or SAS explicitly, describe both scope and expiry as separate properties, and know it bypasses app-tier bandwidth.
Should explain the bearer-token nature, the leak risk that follows from it, and why revocation is limited to expiry or full key rotation.
Should connect this to broader system design: signing-key custody, blast radius of a compromised key, and how this interacts with cost/scaling decisions for the whole platform.
## The problem it solves The **Valet Key** pattern solves a very specific scaling problem: how do you let a client transfer a large blob of data (a photo, a video, a backup file) to or from object storage without forcing every byte of that transfer through your application server? The name comes from the valet parking analogy: a valet key starts a car and lets it be driven a short distance, but can't open the trunk or glovebox, and the owner takes it back when done. The pattern gives clients an equivalent: a temporary, narrowly scoped credential that lets them talk directly to the storage service (Amazon S3, Azure Blob Storage, Google Cloud Storage, etc.) using the storage provider's own API, bypassing your compute tier entirely for the data-plane part of the operation. ## The two phases Mechanically, the flow has two phases. 1. **First**, the client asks your application server for permission to perform some storage operation, such as 'let me upload a file to path X' or 'let me download object Y.' Your server, which already holds long-lived credentials to the storage account (an IAM role, a storage account key, a service principal), performs whatever authorization checks it wants (is this user logged in, do they own this path, are they under quota) and then, instead of doing the transfer itself, cryptographically signs a URL. The server hands this signed URL back to the client. 2. **Second**, the client uses that URL directly against the storage service's REST endpoint. The storage service independently recomputes the HMAC over the incoming request and compares it to the signature embedded in the URL; if they match and the current time is within the stated validity window, the request is allowed, otherwise it is rejected with an authentication error. ## What the server signs On AWS this is a **pre-signed URL**; on Azure it's a **Shared Access Signature** (SAS) token; Google Cloud calls it a signed URL too. The signature is typically an **HMAC** computed, using the server's storage credentials as the signing key, over a canonical description of the intended request, namely: - the HTTP verb - the resource path - the query parameters - an expiration timestamp ## Why the pattern exists The reason this pattern exists is almost entirely about **offloading cost and bottlenecks** from the application tier. If every file upload or download streamed through your app servers: - you would pay compute and bandwidth for data your application logic never actually needs to touch; - your connection pools would be tied up for the duration of large transfers; - your app tier's horizontal scaling would need to track storage traffic rather than business logic traffic. Object storage services are built and priced to handle massive parallel throughput directly; letting clients talk to them natively means the data plane scales independently of, and usually far more cheaply than, the compute plane. ## The trade-off — control versus scale The core trade-off is control versus scale. Once you hand out a signed URL, you have delegated a specific, bounded slice of your storage credentials to code you do not control (the client). Two properties bound that delegation: - **Scope** — the URL is tied to one resource and one verb such as `PUT` to a single object key rather than a blanket grant to the whole bucket. - **Time** — the URL carries an expiration and stops validating shortly after issuance, usually minutes to a few hours. Both properties exist because the token is a **bearer credential**: whoever possesses the URL string can use it, with no additional login step, until it expires or the underlying signing key is rotated. That is the sharpest edge of the pattern: there is no username or password check on the second phase, only whether you possess this exact URL. ## Failure modes That bearer nature creates the pattern's characteristic failure modes. If a signed URL leaks, through browser history, a referrer header, a logging pipeline that captures full request URLs, or a misconfigured CDN cache, anyone who obtains it can exercise whatever scope and time window it was granted, with no further authentication. Because the URL is self-contained and validated purely by signature and clock, most implementations offer no way to revoke a single token early. You either: - wait for it to expire, or - rotate the account's signing key entirely, which kills every outstanding valid URL at once, not just the leaked one. ## Where it shows up A concrete real-world instance: - **Amazon S3 pre-signed URLs** are commonly used so a browser or mobile app can `PUT` a user-uploaded profile photo or video directly to a bucket, with the application server only handling the lightweight step of generating the URL after checking the user is authorized and under quota; the multi-megabyte file transfer itself never touches the app server's compute or network budget. - Similarly, **Azure Blob Storage SAS tokens** back video-ingestion pipelines in media platforms, where an ingestion service issues a short-lived, write-only SAS scoped to a single blob path per upload session, keeping the always-on ingestion service free of the actual video bytes.
- Why does the app server still need to be involved at all if the client is doing the actual transfer?The app server is the only party that holds the long-lived storage credentials and the business context (is this user allowed to write here, are they under quota), so it stays in the loop just long enough to make that authorization decision and sign a scoped, time-limited URL. The heavy data transfer is what gets offloaded, not the authorization decision itself.
- What stops a client from reusing the same pre-signed upload URL to overwrite the file a second time?Nothing inherently does, unless the issuer designs against it; a pre-signed PUT URL is typically reusable for any request matching its signed parameters until it expires, so if single-use semantics matter, the issuer needs to either make the object path unique per attempt or pair the token with an application-level check.
- Is a pre-signed URL a form of authentication or authorization?It's closer to a capability token: it doesn't identify who the bearer is, it just grants a specific, bounded capability to whoever holds it, which is why it's evaluated purely by signature and time rather than by checking an identity on each use.
Like a valet key for a car: it starts the ignition and drives the car a short distance, but can't open the trunk or glovebox, and it stops working once you get your real key back — anyone holding that literal valet key can drive off with the car until it's returned.
saying these in an interview costs you the question
- Says the app server proxies the bytes but still calls it Valet Key
- Doesn't know the URL is a bearer credential usable by anyone who has it
- Thinks the token can be revoked instantly by default
- Grants scope broader than needed, like whole-bucket access for a single file
- No mention of expiry at all, treating the token as a long-lived credential
- Assumes the storage service asks the app server to re-check anything on each use