Skip to content

Conversation

@haacked
Copy link
Contributor

@haacked haacked commented Dec 3, 2025

Add support for HTTP conditional requests using ETags to reduce bandwidth when polling for feature flag definitions. When flag definitions haven't changed, the server returns 304 Not Modified and the SDK skips processing.

Based on PostHog/posthog-python#381

Use conditional requests with If-None-Match header to reduce bandwidth
when polling for feature flag definitions. The server returns 304 Not
Modified when flags haven't changed, avoiding unnecessary data transfer.

- Store ETag from server responses
- Send If-None-Match header on subsequent requests
- Handle 304 Not Modified by keeping cached flags
- Clear ETag on quota limit (402) or when server stops sending it
Move defer res.Body.Close() immediately after the error check to ensure
the response body is closed for all status codes, not just 200 OK.

Previously, early returns for 304 Not Modified and 402 Payment Required
would skip the defer, causing connection pool leaks over time.
- Use GetFeatureFlags() which blocks until initial fetch completes
- Use waitForCondition() helper with polling for ForceReload operations
- Use atomic.Value instead of mutex for thread-safe string storage
- Tests are now faster (0.06s vs 1.22s) and more reliable
Verify that the stored ETag is preserved when the server returns a 304
Not Modified response without including an ETag header. This is an edge
case but ensures defensive behavior.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds HTTP conditional request support using ETags to the feature flags polling mechanism for local evaluation. When flag definitions haven't changed, the server can return a 304 Not Modified response, allowing the SDK to skip reprocessing and reduce bandwidth consumption.

Key changes:

  • Added flagsEtag field to FeatureFlagsPoller to store the current ETag
  • Modified fetchNewFeatureFlags() to send If-None-Match headers and handle 304 responses
  • Added comprehensive test coverage for various ETag scenarios

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
featureflags.go Implements ETag storage, conditional request headers, and 304 response handling in the feature flags polling logic
featureflags_etag_test.go Adds comprehensive test coverage for ETag functionality including storage, conditional requests, 304 handling, ETag updates, and edge cases

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@haacked haacked requested a review from Copilot December 3, 2025 16:28
@haacked haacked marked this pull request as ready for review December 3, 2025 16:28
@haacked haacked requested review from a team and orian December 3, 2025 16:28
@posthog-project-board-bot posthog-project-board-bot bot moved this to In Review in Feature Flags Dec 3, 2025
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

return
}
defer cancel()
defer res.Body.Close()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved this call here because before:

  • If status was 402 (quota limit) → returned early, body never closed (leak!)
  • If status was not 200 → returned early, body never closed (leak!)

Adds an interactive example to demonstrate ETag support for local
evaluation polling. The example polls every 5 seconds and logs
the If-None-Match header sent and the response status (200 vs 304)
to show when cached flags are used.
@github-project-automation github-project-automation bot moved this from In Review to Approved in Feature Flags Dec 4, 2025
Per review feedback, this makes the tests simpler.
@posthog-project-board-bot posthog-project-board-bot bot moved this from Approved to In Review in Feature Flags Dec 4, 2025
@haacked haacked merged commit c4e9b4f into master Dec 4, 2025
9 checks passed
@github-project-automation github-project-automation bot moved this from In Review to Done in Feature Flags Dec 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants