Published December 15, 2022

Why We Reluctantly Chose Go Over Elixir

When building a startup, every technical decision matters. Here's why we chose Go over Elixir for our feedback management platform - and why we might switch back later.

T

Tyler Sustare

Author

8 min read

When building Feedback Frog, every technical decision matters. As we architected our feedback management platform, we faced a choice between Go, Elixir, and the JavaScript/TypeScript ecosystem for our backend infrastructure. While all three have passionate advocates, we ultimately chose Go – and the reasoning might surprise you.

The AI-Assisted Development Reality

Here’s something most startup blogs won’t tell you: your choice of programming language directly impacts how much help you can get from AI coding assistants. Having worked extensively with Ruby at Shopify, we know its rough edges intimately – and we also know how incredible the AI support is for Ruby development.

We tested this hypothesis with GitHub Copilot and other AI tools across multiple languages while prototyping Feedback Frog. The results were clear but disappointing: Ruby gets the best AI support, followed by JavaScript/TypeScript and Go, with Elixir trailing significantly behind.

I’ll be honest – this makes me sad. I want Elixir to be the front runner. The language is elegant, the Actor model is brilliant for real-time feedback processing, and OTP is a masterpiece of fault-tolerant design. But the reality is harsh: AI tools just aren’t as helpful with Elixir development.

Go’s AI-Friendly Characteristics

Here’s something interesting we discovered: Go is a bit cumbersome to write by hand, but much easier to read than most languages. This turns out to be perfect for AI-assisted development.

Go’s verbosity and explicit error handling feel tedious when you’re typing every character yourself. But when an AI assistant is writing the boilerplate for you, that same verbosity becomes a superpower:

  • Explicit types mean the AI knows exactly what methods are available
  • Verbose error handling is generated automatically instead of being a burden
  • Simple syntax means fewer ways for the AI to get confused
  • Standard formatting (gofmt) means consistent, readable output

The language that feels “boring” to write manually becomes incredibly productive when you’re pair-programming with an AI that handles the tedious parts.

The JavaScript/TypeScript Dilemma

JavaScript and TypeScript deserve special mention here. The AI support is excellent – second only to Ruby in our testing. The language is ubiquitous, and AI assistants are incredibly helpful with modern JS/TS patterns.

But as we’re building Feedback Frog in late 2022, the Node.js/Deno ecosystem is fragmented in concerning ways:

  • Runtime uncertainty: Node.js vs Deno vs the new kid Bun – who will win?
  • Framework wars: Express vs Fastify vs Koa vs newer players
  • Tooling chaos: Webpack vs Vite vs esbuild vs Rollup
  • Package management: npm vs yarn vs pnpm drama

Despite JavaScript’s fantastic AI support, we can’t confidently bet on which stack will emerge as the winner. The ecosystem feels like it’s still figuring itself out.

The Ruby Reality Check

Ruby has incredible AI support on the surface, but there’s a hidden problem: Ruby’s typing system can make LLMs have a hard time knowing which methods exist on a Ruby object. Even with Sorbet typing, the dynamic nature of Ruby means AI assistants often suggest methods that don’t exist or miss the ones that do.

From our Shopify days, we also know Ruby’s real scaling challenge isn’t performance – it’s the cost of scaling. Ruby can handle massive loads, but you’ll pay dearly for the compute resources to make it happen. When you’re building infrastructure that needs to be profitable at scale, those hosting costs matter.

Why the Difference in AI Support?

It comes down to training data volume and type safety:

Ruby’s complicated dominance: Massive training data but dynamic typing creates confusion for AI assistants about available methods.

JavaScript/TypeScript’s strength: Ubiquitous language with massive amounts of training data, plus TypeScript gives AI models the type information they need.

Go’s solid position: GitHub hosts millions of Go repositories. The static typing, explicit interfaces, and readable syntax make AI assistance both reliable and accurate. The verbosity that feels cumbersome to write manually becomes an asset when AI is doing the writing.

Elixir’s niche reality: Despite having the best documentation of any language I’ve used, Elixir remains specialized. The smaller community means less training data for AI models, and it shows when building complex feedback routing systems.

What This Means for Feedback Frog

When you’re building a platform that needs to handle feedback from thousands of companies cost-effectively:

  • Ruby: Best AI support by volume, but dynamic typing confuses LLMs, and scaling costs are brutal
  • JavaScript/TypeScript: Excellent AI assistance, but ecosystem fragmentation makes us nervous
  • Go: Great AI assistance with static typing that LLMs understand, plus the verbosity that’s annoying to write manually becomes productive when AI handles it
  • Elixir: AI handles basic patterns but struggles with advanced OTP concepts we’d need for distributed feedback processing

We ruled out Ruby immediately. The AI support is tempting, but the combination of type confusion for LLMs and expensive scaling made it a non-starter for infrastructure software.

JavaScript/TypeScript is tempting, but without clear framework winners, we might as well use Go and let each service use the best tool for the job.

Our Current Architecture

We chose Go with a service-oriented approach:

  • Twirp services with protobuf for internal service-to-service communication
  • REST APIs with standard Gin for external-facing endpoints
  • VMs with persistent storage for rate limiting packages and core infrastructure

This approach gives us:

  • Predictable performance for feedback ingestion
  • Simple deployment story (single binaries)
  • Excellent AI assistance that understands our types and generates readable, explicit code
  • Clear service boundaries with the right tool for each job
  • Cost-effective horizontal scaling as we add customers

The Elixir Reevaluation

Here’s where it gets interesting: we’re planning to reevaluate Elixir when we need to distribute and cluster our APIs across regions.

As Feedback Frog grows and we need true distributed feedback processing – routing feedback across geographic regions, handling complex real-time collaboration, and managing fault tolerance across data centers – Elixir’s OTP and Actor model start to look incredibly attractive.

The features that make Elixir perfect for our future needs:

  • Real-time feedback routing across global infrastructure
  • Fault tolerance for handling feedback spikes and regional outages
  • Hot code updates for zero-downtime deployments
  • Built-in clustering for seamless geographic distribution

Beyond AI: Go’s Current Advantages

Don’t get us wrong – we didn’t choose Go solely for AI support. For our current phase, Go brings startup-friendly benefits:

  • Hiring: Much larger talent pool as we build our team
  • Performance: Perfect for high-throughput feedback APIs
  • Cost efficiency: Excellent performance per dollar spent on infrastructure
  • Ecosystem: Mature, stable libraries with clear winners
  • Deployment: Single binary deployments are startup gold
  • Service architecture: Easy to mix Twirp and REST as needed
  • Code review: The explicit, readable nature makes team collaboration smoother

The Feedback Frog Evolution

Our technical strategy reflects our product roadmap:

Phase 1 (Current): Service-oriented feedback processing with Go

  • Twirp for internal communication, Gin for REST APIs
  • Simple, fast, AI-assisted development where verbosity becomes productivity
  • Cost-effective scaling with VMs and persistent storage
  • Focus on core feedback management features

Phase 2 (Future): Distributed, real-time feedback infrastructure

  • Geographic distribution for global customers
  • Complex routing and real-time collaboration
  • This is where Elixir’s strengths become essential

The Bottom Line

In the age of AI-assisted development, both language popularity and type clarity matter more than ever for rapid iteration. Go’s combination of static typing, explicit syntax, and readability makes it particularly well-suited for AI pair programming – the verbosity that feels tedious to write manually becomes an asset when your AI assistant handles the boilerplate.

While JavaScript/TypeScript has excellent AI support, the fragmented ecosystem makes us hesitant to bet on any particular stack. While Ruby has great AI support by volume, the dynamic typing confuses LLMs and the scaling costs are prohibitive for infrastructure. While we love Elixir’s elegance and its perfect fit for distributed feedback systems, Go’s mature ecosystem – amplified by AI-friendly characteristics – makes it the pragmatic choice for getting Feedback Frog to market quickly and cost-effectively.

But we’re not married to this decision. As we scale globally and need true distributed processing, Elixir might become the obvious choice for our infrastructure.

The best technical decision is the one that gets your product to customers fastest – everything else can be refactored later.


Building feedback infrastructure? We’re always interested in talking to teams about their technical challenges. Reach out to us at hello@feedbackfrog.com

T

About Tyler Sustare

Passionate about building great products and sharing insights on software development, startup culture, and technical architecture. Always learning, always shipping.

Related Articles

Stay in the Loop

Get the latest insights on building better products delivered to your inbox