https://github.com/vmarlier/flowstate
FlowState is a dynamic L7 Reverse Proxy built in Go using only the stdlib.
https://github.com/vmarlier/flowstate
golang learning-by-doing reverse-proxy stdlib-only
Last synced: 18 days ago
JSON representation
FlowState is a dynamic L7 Reverse Proxy built in Go using only the stdlib.
- Host: GitHub
- URL: https://github.com/vmarlier/flowstate
- Owner: vmarlier
- Created: 2026-05-01T22:04:47.000Z (about 2 months ago)
- Default Branch: main
- Last Pushed: 2026-05-03T10:59:24.000Z (about 2 months ago)
- Last Synced: 2026-05-03T12:29:46.000Z (about 2 months ago)
- Topics: golang, learning-by-doing, reverse-proxy, stdlib-only
- Language: Go
- Homepage:
- Size: 16.6 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# FlowState
Golang stdlib-only
> [!NOTE]
> Constraint: This project strictly uses the Go Standard Library. No external dependencies are permitted, ensuring a deep dive into core system engineering principles and the Go runtime.
FlowState is a dynamic L7 Reverse Proxy built in Go using only the stdlib.
## Idea
### Design goals
- Build a **stdlib-only Layer 7 reverse proxy** to understand HTTP internals, connection reuse, and request lifecycle.
- Implement **explicit routing, backend selection, and middleware composition** without framework abstractions.
- Make **timeouts, cancellation, health state, and observability** first-class so behavior under failure is understandable.
- Favor **clear control flow and measurable correctness** over feature count.
### Non-goals
- Not a production replacement for Envoy, NGINX, or Traefik.
- No dynamic control plane, distributed config, or service discovery at first.
- No HTTP/3, gRPC-native balancing, or WASM/plugin ecosystem.
- No external metrics/tracing libraries.
### Architecture
- Ingress path: `net/http` server accepts request.
- Router: matches host/path/method to a route entry.
- Middleware chain: request ID, logging, rate limiting, recovery, optional auth later.
- Load balancer: selects a healthy backend for the route.
- Proxy layer: rewrites request, injects forwarding headers, strips hop-by-hop headers, forwards via custom `http.RoundTripper`.
- Health subsystem: active probes + passive failure observation update backend state.
- Metrics/admin endpoints: expose counters, latency buckets, backend health.
Internal flow: `server -> router -> middleware -> lb -> proxy transport -> response filters -> metrics`
### Failure model
- If a backend times out, connection fails, or returns repeated 5xx responses, it may be marked unhealthy and removed from rotation.
- If all backends are unavailable, return `502` or `503` consistently.
- Client cancellation propagates to backend requests through `context.Context`.
- On shutdown, stop accepting new requests and allow in-flight requests to drain for a bounded time.
- No guarantee of zero request loss during process crash or forced termination.
### Benchmark plan
Measure with `testing.B`, `httptest`, and simple load tools.
- Requests/sec through proxy with 1, 10, 100 concurrent clients.
- Latency: p50/p95/p99 under healthy backends.
- Tail latency under one slow backend.
- Cost of middleware stack.
- Effect of connection reuse vs disabled keep-alive.
- Load-balancer distribution fairness across backends.
### Test strategy
- Unit tests for router matching, backend selection, health transitions, middleware behavior.
- `httptest.Server` integration tests for end-to-end proxying.
- Timeout/cancellation tests with slow handlers and canceled contexts.
- Race-detector runs for backend state, counters, and health updates.
- Fuzz tests for route parsing, config parsing, and header rewriting.
- Deterministic failure injection for connection errors and backend flapping.
---
### Core (v0.1)
- [X] **Static config loader**
- Use: `encoding/json` or `encoding/gob`/custom parser, `os`, `flag`
- Learn: config modeling, validation, immutable runtime config
- [ ] **HTTP server bootstrap**
- Use: `net/http`, `context`, `os/signal`
- Learn: server lifecycle, graceful shutdown, deadline propagation
- [ ] **Basic route matching**
- Start simple: exact path + prefix match, host/method aware
- Use: slices/maps, longest-prefix match
- Learn: request dispatch, matching semantics
- [ ] **Custom reverse proxy path**
- Use: `net/http`, `net/url`, `io`, custom handler instead of magic wrappers
- Learn: request cloning, upstream URL rewriting, response copying
- [ ] **Custom transport**
- Use: `http.Transport`
- Learn: keep-alives, `MaxIdleConns`, `MaxIdleConnsPerHost`, dial timeout, TLS handshake timeout, response header timeout
- [ ] **Forwarding and hop-by-hop header handling**
- Learn: `X-Forwarded-For`, `X-Forwarded-Proto`, RFC hop-by-hop header stripping
- [ ] **Weighted round robin**
- Learn: stateful load balancing, atomic counters vs mutexes, fairness
### Correct (v1.0)
- [ ] **Request-scoped context and timeouts**
- Use: `context.WithTimeout`
- Learn: cancellation propagation, bounded resource usage
- [ ] **Structured logging**
- Use: `log/slog`
- Learn: request lifecycle logging, correlation IDs
- [ ] **Request ID middleware**
- Use: headers + context values
- Learn: cross-cutting concerns, observability basics
- [ ] **Recovery middleware**
- Use: `defer`, `recover`
- Learn: panic boundaries in servers
- [ ] **Active health checks**
- Use: `time.Ticker`, `net/http` or `net.DialTimeout`
- Learn: health probe design, state transitions
- [ ] **Passive health checks**
- Learn: consecutive failure counting, decay/reset, backend ejection
- [ ] **Consistent unhealthy-backend policy**
- Learn: fail-open vs fail-closed, cooldowns
- [ ] **Graceful shutdown and backend draining**
- Use: `http.Server.Shutdown`
- Learn: lifecycle management under load
- [ ] **Metrics endpoint**
- Use: `expvar` or custom text format via `net/http`
- Learn: counters, gauges, latency buckets
### Performance (v1.1)
- [ ] **Trie router only if route count justifies it**
- Learn: radix tree / trie, path parameter trade-offs
- [ ] **Power of Two Choices**
- Learn: queue-aware balancing, herd effect mitigation
- [ ] **Token bucket rate limiter**
- Use: `time`, `sync`, monotonic refill math
- Learn: admission control, backpressure
- [ ] **Connection pool tuning benchmarks**
- Learn: transport tuning under concurrency
- [ ] **Latency histograms / approximate percentiles**
- Learn: buckets vs exact percentiles, tail latency measurement
- [ ] **Zero-allocation hot-path cleanup where useful**
- Learn: buffer reuse, avoiding needless header/value copies
### Advanced (v2.0)
- [ ] **Circuit breaker**
- Learn: closed/open/half-open FSM, rolling failure windows
- [ ] **Hot config reload**
- Use: atomic config swap, signal-driven reload
- Learn: read-copy-update style config management
- [ ] **Per-route middleware policies**
- Learn: policy composition and precedence
- [ ] **Retry policy for idempotent requests only**
- Learn: retry safety, duplicate side effects
- [ ] **Outlier detection**
- Learn: passive latency/error-based backend suppression