Problem
coder/hnsw depends on google/renameio which does not compile on Windows. Currently, Windows builds fall back to BruteForceIndex (O(n) search, no persistence) via build tags (hnsw_windows.go).
Root Cause
The renameio dependency is used in exactly one function: SavedGraph.Save() in encode.go for atomic file writes. google/renameio will never support Windows — this is a deliberate design decision.
Proposed Solution
Fork coder/hnsw and replace renameio with natefinch/atomic, which supports Windows via MoveFileExW. The change is ~20-30 lines in a single file.
The coder/hnsw maintainer has described exactly what he wants in a previous (closed) PR:
- Replace
renameio.TempFile + CloseAtomicallyReplace with atomic.WriteFile
- Use
io.Pipe + bufio buffering on both sides to avoid doubling peak memory
g.Export(wr) writes into pipe writer, atomic.WriteFile(path, pipeReader) reads from pipe reader
Implementation Plan
- Fork
coder/hnsw → nvandessel/hnsw
- Apply the
natefinch/atomic + io.Pipe fix
- Add
replace directive in go.mod
- Delete
hnsw_windows.go and remove //go:build !windows tags from hnsw.go / hnsw_test.go
- Submit the same fix upstream as a PR to
coder/hnsw (ref: issue #9)
- Once merged upstream, remove the
replace directive
Context
- coder/hnsw#9 — Windows Compatibility (closed without fix)
- coder/hnsw#12 — Previous PR (closed due to tone, not approach)
- google/renameio#1 — Windows will never be supported
- Current workaround:
internal/vectorindex/hnsw_windows.go (BruteForceIndex fallback)
Alternatives Considered
| Option |
Verdict |
google/renameio/v2 |
Does not support Windows either |
fogfish/hnsw |
Different API, low adoption (18 stars), no built-in persistence |
Bithack/go-hnsw |
Abandoned since 2017 |
| Keep brute-force fallback |
Acceptable short-term but doesn't scale |
Problem
coder/hnswdepends ongoogle/renameiowhich does not compile on Windows. Currently, Windows builds fall back toBruteForceIndex(O(n) search, no persistence) via build tags (hnsw_windows.go).Root Cause
The
renameiodependency is used in exactly one function:SavedGraph.Save()inencode.gofor atomic file writes.google/renameiowill never support Windows — this is a deliberate design decision.Proposed Solution
Fork
coder/hnswand replacerenameiowithnatefinch/atomic, which supports Windows viaMoveFileExW. The change is ~20-30 lines in a single file.The
coder/hnswmaintainer has described exactly what he wants in a previous (closed) PR:renameio.TempFile+CloseAtomicallyReplacewithatomic.WriteFileio.Pipe+bufiobuffering on both sides to avoid doubling peak memoryg.Export(wr)writes into pipe writer,atomic.WriteFile(path, pipeReader)reads from pipe readerImplementation Plan
coder/hnsw→nvandessel/hnswnatefinch/atomic+io.Pipefixreplacedirective ingo.modhnsw_windows.goand remove//go:build !windowstags fromhnsw.go/hnsw_test.gocoder/hnsw(ref: issue #9)replacedirectiveContext
internal/vectorindex/hnsw_windows.go(BruteForceIndex fallback)Alternatives Considered
google/renameio/v2fogfish/hnswBithack/go-hnsw