January 12, 2026 • Roger

Building Routerly: Architecture Decisions and Trade-offs

Architecture Philosophy: Ship Working Software

When I started Routerly, I had a choice: build something perfect in two years, or build something useful in six months. I chose useful.

This post explains the technical decisions behind Routerly, the trade-offs involved, and why I believe pragmatism beats perfectionism for v1.

Decision 1: Go Wrappers, Not Custom Packet Processing

What I’m doing: Writing Go wrappers around Linux networking tools (primarily nftables)

What I’m NOT doing: Building packet processing from scratch in Go or C

Why Go Wrappers?

The Linux networking stack is mature. We’re talking decades of optimization, battle-testing, and security patches. nftables alone represents years of development by people much smarter than me.

Writing custom packet processing would mean:

Instead, Routerly focuses on the interface layer—translating human-readable commands into proper nftables rules. The kernel does what it does best, and Go does what it does best.

Example Architecture

// User types this
routerly allow home access to internet

// Routerly parses it into structured intent
rule := NetworkRule{
    Source: "home",
    Destination: "internet",
    Action: "allow",
}

// Go wrapper generates nftables commands
nftCmd := rule.ToNftables()
// Executes: nft add rule inet filter forward ip saddr @home_subnet accept

// System applies the rule
exec.Command("nft", nftCmd...).Run()

Clean, testable, maintainable. And if nftables improves tomorrow, Routerly benefits automatically.

Decision 2: Ubuntu Core Foundation

What I’m using: Ubuntu Core (snap-based, transactional, immutable)

What I’m NOT using: Traditional distros like Debian, Alpine, or custom buildroot systems

Why Ubuntu Core?

Deployed edge devices have unique requirements:

  1. Security Updates Must Be Automatic: Operators shouldn’t babysit routers
  2. Failures Must Be Recoverable: Bad updates shouldn’t brick devices
  3. System Must Be Minimal: Attack surface matters

Ubuntu Core delivers:

Yes, snaps add some overhead. Yes, there are lighter options. But for a solo developer prioritizing security and reliability over absolute performance, Ubuntu Core is the right trade-off.

Canonical Partnership Potential

Ubuntu Core also opens doors. Canonical already works with defense contractors and enterprise clients—exactly Routerly’s target market. If Routerly proves useful, there’s partnership potential. If not, it’s still a solid technical foundation.

Decision 3: Natural Language, Not DSLs

What I’m doing: Plain English commands parsed with context awareness

What I’m NOT doing: Creating a domain-specific language (DSL) or YAML-based configuration

The Problem with DSLs

Every network vendor has created their own syntax:

# Cisco
access-list 101 permit ip 192.168.1.0 0.0.0.255 any

# Juniper
set firewall family inet filter INTERNET term ALLOW from source-address 192.168.1.0/24

# iptables
iptables -A FORWARD -s 192.168.1.0/24 -j ACCEPT

# nftables
nft add rule inet filter forward ip saddr 192.168.1.0/24 accept

They’re all expressing the same concept: “Let this subnet access the internet.”

Routerly’s approach:

routerly allow 192.168.1.0/24 access to internet
# or more abstractly
routerly allow home access to internet

The parser understands context. It knows “home” is a network alias. It knows “internet” means “not local subnets.” It generates the right underlying commands automatically.

Decision 4: Incremental Feature Additions

What I’m building: Core routing first, advanced features later

What I’m NOT building: Everything at once

v1.0 Feature Set (Q4 2026 Target)

Future Roadmap (Post-v1.0)

I’m explicitly not trying to compete with pfSense or OPNsense on feature count. Those are mature, full-featured platforms with large communities.

Routerly’s value proposition is simplicity and clarity for specific use cases. Do fewer things, but do them obviously and reliably.

Technical Stack Summary

User Interface
  ├─ CLI (Go binary with natural language parser)
  └─ Future: Web UI for status/monitoring

Application Layer (Go)
  ├─ Command parser (intent extraction)
  ├─ Rule validator (safety checks)
  ├─ Network state manager
  └─ nftables wrapper library

System Layer (Ubuntu Core)
  ├─ nftables (firewall/routing)
  ├─ systemd-networkd (interface config)
  └─ Snap confinement (security)

Hardware Layer
  └─ Standard x86_64 or ARM64 devices

Lessons from Early Development

What’s Working

What’s Challenging

Why This Matters

Every technology decision is a trade-off. I’m optimizing for:

  1. Time to useful: Ship v1.0 in 2026, not 2028
  2. Maintainability: One developer can keep this running
  3. Security: Leverage Ubuntu Core’s built-in protections
  4. Clarity: Code that future contributors can understand

Could I build a faster router? Yes. A more feature-rich router? Probably. A more technically impressive router? Definitely.

But Routerly isn’t about technical impressiveness. It’s about making networking accessible to people who need simple, reliable routing without becoming network engineers.


Comments Welcome

Disagree with these choices? See a better approach? I’m building in public specifically to get feedback.

Open an issue on GitHub or reach out on Twitter. This is v0.1 thinking—everything’s negotiable.


Next post: Parsing Natural Language Commands - The Hard Parts