Skip to content

Add X-Request-Start header middleware#85

Merged
kevinmcconnell merged 2 commits intobasecamp:mainfrom
nateberkopec:x-request-start
Jul 26, 2025
Merged

Add X-Request-Start header middleware#85
kevinmcconnell merged 2 commits intobasecamp:mainfrom
nateberkopec:x-request-start

Conversation

@nateberkopec
Copy link
Contributor

Personally, I'm of the belief that everyone should be measuring their request queue times. To do that, we need something in front of the application stamping requests with an X-Request-Start header, so that our application can read that and calculate time spent queueing.

This is usually done in nginx/some other reverse proxy for those using those projects.

This header and format is a common convention and used by New Relic, Datadog and others. If you use any of these APMs and incoming requests start carrying this header, they'll automatically start calculating request queue time.

I did not include a config option because I felt it was unnecessary.

Adds middleware that sets X-Request-Start header with millisecond timestamp
for request timing measurement. Header format follows convention
of t=<milliseconds_since_epoch>.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Collaborator

@kevinmcconnell kevinmcconnell left a comment

Choose a reason for hiding this comment

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

Thanks @nateberkopec, this is great!

I did not include a config option because I felt it was unnecessary.

Agreed, yes. Much prefer just doing this automatically 👍

I've left one comment for you, but otherwise LGTM.

func NewRequestStartMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
timestamp := time.Now().UnixMilli()
r.Header.Set("X-Request-Start", fmt.Sprintf("t=%d", timestamp))
Copy link
Collaborator

Choose a reason for hiding this comment

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

If this header already exists in the request, I don't think we should overwrite it. For example, Kamal-deployed apps will already have an X-Request-Start because we populate it in the proxy. We'll presumably want the queue time to reflect that initial entrypoint.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point, I didn't realize that was a common setup.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@kevinmcconnell
Copy link
Collaborator

Great, thanks again @nateberkopec, I'll get this out in the next release.

@kevinmcconnell kevinmcconnell merged commit 0d3d124 into basecamp:main Jul 26, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants