authors: Bryon bryon@fryer.io state: pre-discussion labels: language-choice, golang, engineering date: 2025-07-20
Choosing Golang as the Primary Language
Summary
This RFD proposes adopting Go (Golang) as the primary implementation language for our backend and systems-level development. Go offers simplicity, performance, strong concurrency primitives, and a thriving ecosystem that aligns well with our goals for maintainability, reliability, and developer productivity.
Motivation
We need a language that:
- Produces reliable, fast binaries
- Has a low barrier to entry for new contributors
- Encourages maintainable and readable code
- Supports concurrency with minimal cognitive overhead
- Has excellent tooling and ecosystem support
- Offers a strong standard library for networking, file I/O, and HTTP
Requirements
The primary language should:
- Be simple to learn and onboard new developers
- Support high-concurrency and networked systems efficiently
- Provide cross-platform compilation with minimal setup
- Have a strong ecosystem of open source libraries and tooling
- Be used widely in production by companies operating at scale
- Offer first-class support for testing and static analysis
- Enable fast iteration and deployment without lengthy build chains
Evaluation
| Language | Simple Syntax | Concurrency | Ecosystem | Binary Output | Tooling | Adoption |
|---|---|---|---|---|---|---|
| Go | ✅ | ✅ Goroutines, Channels | ✅ Robust, Standardized | ✅ Single binary | ✅ go fmt, go test, go vet, gopls |
✅ Google, Uber, Cloudflare, etc. |
| Rust | ❌ Complex | ✅ tokio, async/await |
✅ Strong | ✅ | ✅ Excellent, but heavy | ✅ Dropbox, AWS, Meta |
| Python | ✅ | ❌ GIL limits concurrency | ✅ Rich | ❌ Needs interpreter | ✅ Excellent | ✅ Google, Instagram |
| Node.js | ✅ | ✅ Event-loop model | ✅ Large but fragmented | ❌ Requires runtime | ✅ Good, npm-heavy | ✅ Vercel, Netflix |
| Java | ❌ Verbose | ✅ Threads, Loom (preview) | ✅ Mature | ✅ JVM-based | ✅ Heavyweight | ✅ Everywhere |
Benefits of Go
- Simplicity: Go has a small surface area; developers can become productive quickly.
- Concurrency: Goroutines and channels provide a clean abstraction over threads and async code.
- Tooling: The Go toolchain is self-contained and includes built-in formatting, testing, vetting, and documentation tools.
- Deployment: Statically linked binaries make deployment trivial and reduce runtime surprises.
- Community: Large, vibrant open-source community with active development and library support.
- Performance: Close to C-level performance with minimal optimization effort.
Risks and Tradeoffs
- Runtime GC: Garbage collection introduces non-deterministic pauses, though this is usually negligible.
- No exceptions: Go prefers explicit error handling; this is stylistically different from some other languages.
- Not as low-level as Rust or C: Go is not designed for systems programming requiring strict control over memory layout.
Alternatives Considered
- Rust: Excellent for performance and safety, but significantly higher complexity and slower iteration time.
- Python: Excellent for scripting and data tasks but lacks performance and concurrency for backend systems.
- JavaScript/Node.js: Good for fast prototyping but less suited for long-lived backend services with heavy concurrency.
Recommendation
Adopt Go as the primary language for:
- Backend services
- Network proxies, schedulers, or agents
- Internal tooling
- CLIs and infrastructure automation
Project Fit: buylater.email
The buylater.email project is a strong match for Go, due to its focus on minimalism, privacy, and deterministic backend behavior. The core architectural needs include:
- Stateless HTTP endpoints for link submission, confirmation, and unsubscribe
- Scheduled email delivery without persistent infrastructure
- Secure, tokenized URLs for one-click interactions
- Transparent, inspectable code that can run on cheap VPS or on-prem
Go is particularly well suited here because:
- It supports zero-dependency deployments — one static binary does it all
- It includes robust native libraries for
net/http,crypto,html/template,context, andtime - Its concurrency model is ideal for building timed job schedulers and retry queues
- Go makes it easy to avoid shelling out — all logic can live safely in a single process
- Low cold start time and predictable memory usage enable frictionless hosting
We also expect the project to scale to serve thousands of scheduled reminders per day, a throughput well within Go’s sweet spot for low-latency I/O and CPU-light tasks.