When building Proxylity UDP Gateway we faced a critical product decision: where should we focus our initial developer experience efforts? Conventional wisdom would suggest prioritizing a sleek web dashboard or a fully-featured API. Instead, we made an unconventional choice to put Infrastructure-as-Code (IaC) first.
In this article, we'll explore why we believe this decision works for us, how it creates a superior developer experience for our customers, and aligns with our mission to help teams innovate and experiment quickly.
The "Conventional" Paths
Let's start with the alternatives we considered:
- API-First: Develop comprehensive REST APIs first, then build UIs and other interfaces on top
- Dashboard-First: Create an intuitive web UI that guides users through configuration and deployment
- IaC-First: Develop robust CloudFormation resources that integrate seamlessly with customers' existing infrastructure code
- MCP-First: Prioritize integration with coding Agents by providing capable Model Content Protocol tooling
The API-first approach continues as the tech industry standard, though often surfaced via Model Content Protocols recently. The dashboard-first approach is likewise a part of the SaaS playbook. But neither aligned with how our most successful customers actually work and innovate.
We're 100% on IaC and CI/CD internally -- we believe in it, and we want to make it easy for our customers to use it too. This isn't just a philosophical stance, it's rooted in practical benefits for development teams and the thousands of deployments we delivered this year.
Why IaC Enables Faster Innovation
Infrastructure-as-Code isn't just another deployment method. Defining systems as code (preferably declaratively) represents a fundamental shift in how teams build, test, and evolve cloud systems. It's not magic, though it isn't familiar to everyone. Here's why it accelerates innovation:
1. Version Controlled Infrastructure
When infrastructure is defined in code (as text), you gain all the benefits of version control:
- The history of changes
- Rollbacks when needed
- Branch-based experimentation without risk
- Code reviews for changes
- Automated testing
This takes something you carefully manipulate through clicking a UI or typing in a CLI based on perhaps accurate instructions and memory to something you can iterate on with confidence.
2. Environment Consistency
With IaC, creating identical environments for development, testing, and production becomes trivial:
# Create development environment aws cloudformation deploy \ --template-file udp-gateway.yaml \ --stack-name dev-udp-gateway # Create staging environment with identical configuration aws cloudformation deploy \ --template-file udp-gateway.yaml \ --stack-name staging-udp-gateway
This consistency eliminates the "it works on my machine" problem and reduces the risk of deployment failures. It requires high-quality and adaptive templates.
3. Automated Deployment Pipelines
IaC templates can be easily integrated into CI/CD pipelines, enabling:
- Automatic validation of changes before deployment
- Automatic deployment on code changes
- Automatic roll-back when needed
- Coordination between application and infrastructure changes
This automation removes friction and risk from the deployment process, allowing teams to ship changes more frequently with less manual effort. Having confidence in deployment automation has been a giant productivity boost at Proxylity, reducing the drama of releases to simply pushing changes.
4. Documentation as Code
IaC templates serve as self-documenting artifacts. Though tedious to read they contain all the necessary detail. With LLM summaries, they become more accessible. We've found that maintaining separate documentation that quickly becomes outdated is unnecessary because the infrastructure code itself describes exactly what resources exist and how they're configured. And while LLM generated summaries and help can be wrong, they seem to be less wrong than outdated and incomplete documentation.
The Challenge of Providing IaC-First on AWS
While we believe deeply in the IaC-first approach, we're not blind to its challenges. We looked at the options, old and new, and weighed their trade-offs.
- Custom Resources Are Difficult to Make Safe: Because the older "Custom Resources"
approach exposes the
ServiceTokenARN, which is a resource operated by Proxylity, there is a risk of abuse. Unfortunately the only resource types available for use asServiceTokenimplementations are Lambda Functions and SNS topics. Securing access to them to only subscribers is challenging since IAM requires identifying each individual account and policy sizes are limited. Custom Resources also involve "boilerplate" in templates, inflating the perceived complexity. - Resource Providers Add Friction: Enabling a good onboarding experience for CloudFormation Resource Providers (the new way of providing custom resources) is challenging. On the plus side they add versioning and customer control over availability. Unfortunately, customers need to manually enable them in each account and region where the resource type will be used. That friction hits at a time when it is least welcome -- onboarding. We want a smooth, friction free (no surprises) experiences for new customers and this isn't it.
- Marketplace Quickstart Templates Add "Different" Friction: SaaS products like UDP Gateway sold in AWS Marketplace can provide "quick start" templates that provision resources at the time of subscription. Unfortunately the customer experience is a little byzantine and again hits at onboarding.
Custom Resources Provide the Best Developer Experience
Despite the challenges they create for Proxylity, we believe the old-school custom resources provide the best developer experience for our customers:
No Onboarding Friction
Our mechanism for custom resources means customers get immediate access upon creating a subscription, and can start deploying resources without additional setup steps or delay. We provide examples and templates (and a Terraform module) that work "out of the box" to help developers' "day one" experiences and jump-start learning.
Declarative Configuration
CloudFormation's declarative model allows you to specify the desired state rather than the steps to get there. This makes templates more concise and easier to reason about:
Resources:
MyUdpListener:
Type: Custom::ProxylityUdpGatewayListener
Properties:
Protocol: udp
Destinations:
- Description: "Lambda UDP Handler"
Batching:
Count: 10
TimeoutInSeconds: 1.0
DestinationArn: !GetAtt UdpLambdaFunction.Arn
This declarative approach lends itself naturally to infrastructure that self-heals and maintains its desired state.
Native AWS Integration
Our custom resources integrate natively with AWS CloudFormation, which means:
- They appear in the AWS Console alongside other resources
- They work with AWS CloudFormation's existing tooling and workflows
- They benefit from CloudFormation's safety features like rollback on failure
- They can reference and be referenced by other AWS resources
This integration allows managing UDP Gateway resources alongside the rest of your AWS infrastructure, creating a uniform and cohesive deployment experience.
Multi-Region Resilient
Our custom resources are the control plane for customer resources and so are designed to be resilient with redundant deployment across multiple AWS regions, ensuring high availability and fault tolerance.
Innovation-Friendly
The IaC approach combined with our "pay for what you use" model naturally supports experimentation and innovation:
- Create a new branch for your new idea
- Modify or extend your CloudFormation template to explore options
- Deploy to a staging environment quickly with little or no cost or risk
- Iterate quickly and learn from results
- If the idea is successful, merge to production; if not, simply discard the branch and delete the resources
This workflow allows teams to experiment with confidence, knowing they can easily roll back or iterate based on results. More things can be tried, left to simmer and evolve over time (or discarded).
Getting Started with UDP Gateway via IaC
If you're ready to try our IaC-first approach, here's how to get started:
1. Explore Our Examples Repository
We've created an examples repository with turn-key demonstrations of common UDP Gateway patterns and configurations. These examples serve as both documentation and starting points for your own implementations.
git clone https://github.com/proxylity/udp-gateway-examples.git cd udp-gateway-examples
2. Start with a Template
Begin with one of the .NET templates, and create a UDP or WireGuard Listener and Lambda Destination as a starting point:
dotnet new install Proxylity.Templates dotnet new proxylity-udp-async-aot -n "MyCo.UdpHandler"
3. Deploy and Iterate
Deploy your template and start iterating on it:
sam deploy --guided
As you learn and evolve your solution, your infrastructure code evolves with you, documenting your journey and enabling easy sharing with team members.
The Future of Our Developer Experience
Our commitment to IaC-first doesn't mean we won't provide other interfaces. We are actively working on improvements and expansion of our templates and SDK, as well as:
- REST APIs for programmatic control and integration
- CLI tools for direct command-line interaction
- AI Agent integration tooling with packet comprehension
All of these experiences will build upon the solid foundation of our CloudFormation integration, ensuring consistency across interfaces.
Conclusion: Unconventional with Intent
UDP Gateway is not a conventional product, it defines a new way of working with UDP. Proxylity is not a conventional company. Our IaC-first approach reflects our belief that the best developer experiences align with how developers actually work, not with how products like ours are traditionally built. It's about you, not us.
Our goal is to enable the replacement of aging, legacy server software to drive innovation, and we believe that modern infrastructure deserves modern deployment methods. By prioritizing Infrastructure-as-Code, we enable our customers to innovate faster, experiment more confidently, and build more reliable and valuable systems.
So consider giving UDP Gateway a try. If you like it, keep using it. If you don't, ignore it. But if you have any issue at all getting it set up or building a service with it, please let us know. If you're building a server-based UDP or WireGuard service and can't go faster with UDP Gateway, tell us why and what we can do better.