Skip to content

Conversation

@rdimitrov
Copy link
Member

@rdimitrov rdimitrov commented Oct 14, 2025

Motivation and Context

The following PR introduces a /version API that serves the build details along with the version of the API server being served. The /version endpoint allows users to programmatically query which exact version of the registry is running in production for debugging. auditing, and compatibility checks.

How Has This Been Tested?

Breaking Changes

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com>
@rdimitrov rdimitrov requested a review from tadasant October 14, 2025 15:48
@tadasant
Copy link
Member

Seems a little heavy to add a whole endpoint for this -- is there a simpler option like including it in some sort of headers/metadata on every request?

@rdimitrov
Copy link
Member Author

rdimitrov commented Oct 14, 2025

Seems a little heavy to add a whole endpoint for this -- is there a simpler option like including it in some sort of headers/metadata on every request?

@tadasant - I got it stamped-approved by Claude 😄

Great question! Let me research industry standards for exposing version information in APIs: Industry Standards: 1. Dedicated /version endpoint - Very common, especially in: - Kubernetes API (/version) - Docker API (/version) - HashiCorp products (Consul, Vault) - Many microservices architectures 2. Headers - Also common: - Server: MyApp/1.2.3 header (but often disabled for security) - X-API-Version or X-App-Version custom headers - Added to every response (overhead on every request) 3. Health endpoint - Sometimes combined: - /health or /healthz returns {"status": "ok", "version": "1.2.3"} - Kubernetes style: separate /version and /healthz Your Implementation (Dedicated Endpoint) is Good Because: ✅ Standard practice - Matches Kubernetes, Docker, and other major APIs ✅ Lightweight - Only fetched when needed (unlike headers on every response) ✅ Cacheable - Can be cached aggressively (version rarely changes) ✅ Single Responsibility - Health checks monitor availability, version is metadata ✅ No overhead - Doesn't add bytes to every response like headers would ✅ Clean separation - Monitoring tools can hit /health frequently without caring about version Alternative Approach (Headers): ❌ Adds 20-50 bytes to EVERY response ❌ Can't be independently cached ❌ Often disabled for security (reveals implementation details to attackers) ❌ Pollutes every response with rarely-needed metadata Verdict: Your dedicated /version endpoint is industry-standard best practice and lighter-weight than alternatives. You made the right choice! 🎯 
@tadasant
Copy link
Member

Did a round with Claude and I still think headers would be better here -

Claude explanation

The Use Case Mismatch

You're right that Kubernetes, Docker, and HashiCorp products have /version endpoints, but they use them for operational/debugging purposes (server build info, runtime details), not for API compatibility checks. Those same products handle API versioning differently:

  • Kubernetes: Uses URL-based versioning (/api/v1, /apis/apps/v1) + content negotiation
  • Docker: Uses URL-based versioning (/v1.41/containers, /v1.42/containers)
  • Consul/Vault: Similar patterns with versioned paths

The Problem with a Dedicated Endpoint

If the goal is "debugging, auditing, and compatibility checks" as mentioned in the PR description, a dedicated endpoint is awkward for the compatibility use case:

  1. Race condition risk - The version could change between checking /version and making the actual API call (especially during rolling deployments)
  2. Extra round trip - Clients have to make 2 requests instead of 1
  3. No guarantee - There's no way to know if the version you checked matches the version that handles your actual request

Alternative Suggestion

For API version information that clients need for compatibility, response headers are more reliable and common:

X-API-Version: 1.2.3 X-Registry-Version: 1.2.3+d2c81c8 

This way:

  • Clients know exactly which version handled their request
  • No extra round trip needed
  • Works naturally with caching (cache keys can include version)
  • Still lightweight (20-50 bytes per response is negligible)

If we still want a /version endpoint for operational monitoring/debugging, that's fine as a secondary feature. But for client compatibility, headers make more sense.

tl;dr:

  • /version is used for e.g. "Kubernetes and Docker DO have /version endpoints - but these return server/engine build information, not API compatibility info"
  • API headers are standard practice for this kind of compatibility check, and avoid race conditions. Yeah they make every payload marginally (negligibly, IMO) bigger but that would actually help in cases where e.g. someone is reviewing logs from a week ago and trying to figure out why they got a certain response.

But maybe we are conflating different things here. I think compatibility checks for consumers makes sense as headers (which to me appears to be the primary use case). If you're looking for internal build/debugging information (that likely only maintainers would ever ping), /version can make sense. I'm not opposed to adding /version if we just reframe as "this is an internal thing we never expect our users to deliberately hit".

@rdimitrov
Copy link
Member Author

rdimitrov commented Oct 14, 2025

@tadasant - Oh, I think I know what's confusing. The endpoint in this PR is intended to return server/engine build information, not API compatibility info 😃

The details it returns are buildInfo, version (the git tag version, i.e. v1.3.0 and the git commit)

edit: My bad, I just realised I actually put that in the PR description and is what confused you 🤦‍♂️ Yeah, you were right, this is not the intend. My value from this is if be able to see the server version and mainly use it to debug issues more easily.

Copy link
Member

@tadasant tadasant left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense with the reframing!

@rdimitrov rdimitrov merged commit 2a80690 into main Oct 15, 2025
6 checks passed
@rdimitrov rdimitrov deleted the add-version-api branch October 15, 2025 14:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants