From b5b2b6b5da9007b1a06cd7c68d65ee2b1842587d Mon Sep 17 00:00:00 2001 From: Luis Meyer Date: Mon, 2 Mar 2026 16:20:42 +0100 Subject: [PATCH] Add preconnect() to reduce TLS handshake latency Fire a lightweight HEAD request to flags.vercel.com during constructor to warm the connection pool, skipping the full DNS+TCP+TLS handshake on subsequent requests. Includes tests verifying correct headers, build-step skipping, custom fetch usage, and graceful failure handling. Co-Authored-By: Claude Haiku 4.5 --- .../flag-network-data-source.test.ts | 113 ++++++++++++++++++ .../data-source/flag-network-data-source.ts | 16 +++ 2 files changed, 129 insertions(+) diff --git a/packages/vercel-flags-core/src/data-source/flag-network-data-source.test.ts b/packages/vercel-flags-core/src/data-source/flag-network-data-source.test.ts index 07e85ab7..1d49872e 100644 --- a/packages/vercel-flags-core/src/data-source/flag-network-data-source.test.ts +++ b/packages/vercel-flags-core/src/data-source/flag-network-data-source.test.ts @@ -25,6 +25,9 @@ import { readBundledDefinitions } from '../utils/read-bundled-definitions'; let ingestRequests: { body: unknown; headers: Headers }[] = []; const server = setupServer( + http.head('https://flags.vercel.com/v1/datafile', () => { + return new HttpResponse(null, { status: 200 }); + }), http.post('https://flags.vercel.com/v1/ingest', async ({ request }) => { ingestRequests.push({ body: await request.json(), @@ -2066,4 +2069,114 @@ describe('FlagNetworkDataSource', () => { await dataSource.shutdown(); }); }); + + describe('preconnect', () => { + it('should fire HEAD request with correct headers during construction', async () => { + let headRequest: { url: string; headers: Headers } | undefined; + + server.use( + http.head('https://flags.vercel.com/v1/datafile', ({ request }) => { + headRequest = { url: request.url, headers: request.headers }; + return new HttpResponse(null, { status: 200 }); + }), + ); + + new FlagNetworkDataSource({ + sdkKey: 'vf_test_key', + stream: false, + polling: false, + }); + + await vi.waitFor(() => { + expect(headRequest).toBeDefined(); + }); + + expect(headRequest!.url).toBe('https://flags.vercel.com/v1/datafile'); + expect(headRequest!.headers.get('Authorization')).toBe( + 'Bearer vf_test_key', + ); + expect(headRequest!.headers.get('User-Agent')).toMatch( + /^VercelFlagsCore\//, + ); + }); + + it('should not fire during build step', async () => { + let headRequestFired = false; + + server.use( + http.head('https://flags.vercel.com/v1/datafile', () => { + headRequestFired = true; + return new HttpResponse(null, { status: 200 }); + }), + ); + + process.env.CI = '1'; + + new FlagNetworkDataSource({ + sdkKey: 'vf_test_key', + stream: false, + polling: false, + }); + + await new Promise((r) => setTimeout(r, 100)); + + expect(headRequestFired).toBe(false); + }); + + it('should use custom fetch function when provided', async () => { + let customFetchCalled = false; + + const customFetch: typeof globalThis.fetch = async (input, init) => { + if (init?.method === 'HEAD') { + customFetchCalled = true; + } + return globalThis.fetch(input, init); + }; + + new FlagNetworkDataSource({ + sdkKey: 'vf_test_key', + stream: false, + polling: false, + fetch: customFetch, + }); + + await vi.waitFor(() => { + expect(customFetchCalled).toBe(true); + }); + }); + + it('should silently ignore failures', async () => { + server.use( + http.head('https://flags.vercel.com/v1/datafile', () => { + return HttpResponse.error(); + }), + ); + + const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); + + const dataSource = new FlagNetworkDataSource({ + sdkKey: 'vf_test_key', + stream: false, + polling: false, + datafile: { + projectId: 'test', + definitions: { + testFlag: { + environments: { production: 0 }, + variants: [false, true], + }, + }, + environment: 'production', + }, + }); + + await new Promise((r) => setTimeout(r, 100)); + + await dataSource.initialize(); + const result = await dataSource.read(); + expect(result.definitions).toBeDefined(); + + errorSpy.mockRestore(); + }); + }); }); diff --git a/packages/vercel-flags-core/src/data-source/flag-network-data-source.ts b/packages/vercel-flags-core/src/data-source/flag-network-data-source.ts index 8666acb8..f6cc72b6 100644 --- a/packages/vercel-flags-core/src/data-source/flag-network-data-source.ts +++ b/packages/vercel-flags-core/src/data-source/flag-network-data-source.ts @@ -262,6 +262,22 @@ export class FlagNetworkDataSource implements DataSource { sdkKey: this.options.sdkKey, host: this.host, }); + + this.preconnect(); + } + + private preconnect(): void { + if (this.options.buildStep) return; + + void this.options + .fetch(`${this.host}/v1/datafile`, { + method: 'HEAD', + headers: { + Authorization: `Bearer ${this.options.sdkKey}`, + 'User-Agent': `VercelFlagsCore/${version}`, + }, + }) + .catch(() => {}); } // ---------------------------------------------------------------------------