skip to content

questions

5

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?

level: juniorimportance: must knowfreq 70%

answer

  1. valet key = temporary car key
  2. bearer token, not identity
  3. scope + expiry, not one or the other
  4. app server signs, never touches bytes

basics

~20 s

The 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 s

The 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

for a junior

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.

for a middle

Should name pre-signed URL or SAS explicitly, describe both scope and expiry as separate properties, and know it bypasses app-tier bandwidth.

for a senior

Should explain the bearer-token nature, the leak risk that follows from it, and why revocation is limited to expiry or full key rotation.

for a principal

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

context

open as a page

When an application server constructs a pre-signed URL (or Azure SAS token) for a client to upload a single file to object storage, which specific parameters should it constrain to keep the resulting credential least-privilege, beyond just setting an expiry time?

level: middleimportance: must knowfreq 65%

basics

~10 s

It should limit the link to one exact file, one action (like upload-only, not delete), and sometimes the file size or type — not just make the link expire soon.

open as a page

A team is deciding whether to let clients upload directly to object storage via pre-signed URLs, or keep proxying uploads through their application server. Name two concrete scenarios where proxying through the app server is the better choice, and explain why the Valet Key pattern falls short there.

level: seniorimportance: must knowfreq 55%

basics

~20 s

If you need to check, transform, or tightly control the file as it arrives, like scanning for viruses before it's stored or enforcing a quota that can change moment to moment, routing through your server lets you do that inline. Direct-to-storage uploads only let you react after the fact.

open as a page

In production, a system using pre-signed S3 URLs for client uploads starts seeing a spike in 403 SignatureDoesNotMatch and expired-token errors from clients on flaky mobile networks, even though the URLs were generated correctly seconds before use. What are two distinct root causes worth investigating, and how do they differ?

level: seniorimportance: should knowfreq 45%

basics

~20 s

Either the client's clock is off so the link looks expired too early, or the upload got retried in a way that changed something about the request (like its size), so it no longer matches what was originally signed. Both look like the same error but need different fixes.

open as a page

Your organization issues thousands of pre-signed URLs per hour for direct-to-storage access using a single shared account-level signing key. Security now requires the ability to revoke access for a specific issued token within seconds if it's suspected leaked, without breaking every other outstanding URL. How would you redesign the token-issuing architecture to support that?

level: principalimportance: should knowfreq 30%

basics

~20 s

Stop relying on one shared master key for everything. Instead, make each link individually trackable, for example by making tokens expire very fast, or by adding a lookup list of blocked token IDs that gets checked before the request reaches storage, so you can kill one without touching the rest.

open as a page