<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/the-system-design-behind-my-new-saas-n2rai39sp" -->

---
title: The System Design Behind My New SaaS | daily.dev
description: A detailed walkthrough of the system design behind Katabench, a .NET coding platform that safely executes arbitrary C# code submitted by users. The...
canonical: https://daily.dev/posts/the-system-design-behind-my-new-saas-n2rai39sp
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: The System Design Behind My New SaaS | daily.dev
og:description: A detailed walkthrough of the system design behind Katabench, a .NET coding platform that safely executes arbitrary C# code submitted by users. The...
og:url: https://daily.dev/posts/the-system-design-behind-my-new-saas-n2rai39sp
og:image: https://api.daily.dev/og/posts/n2RAI39sp.png
og:image:alt: The System Design Behind My New SaaS
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# The System Design Behind My New SaaS

**[Milan Jovanović](https://daily.dev/sources/milanjovanovic)** · 10 min read · 49 upvotes · 6 comments

## Summary

A detailed walkthrough of the system design behind Katabench, a .NET coding platform that safely executes arbitrary C# code submitted by users. The architecture uses three Hetzner VPS servers: one for the .NET API and Postgres, one for isolated code execution sandboxes, and one for deployment and observability. All servers are connected via a self-hosted Headscale/WireGuard VPN with no public exposure beyond ports 80/443. Code submissions flow through NATS JetStream to a worker that spins up throwaway containers with no network access and strict resource limits. The observability stack uses Grafana, Loki, Tempo, and Prometheus fed by OpenTelemetry collectors. Auth is delegated to Clerk and payments to Paddle (as merchant of record), while everything else is self-hosted on a fixed monthly cost.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://milanjovanovic.tech/blog/the-system-design-behind-my-new-saas>

## Questions this post answers

### How can I safely run untrusted user-submitted code on my own servers instead of a managed sandbox service?

Isolate execution on a dedicated worker server with no database connection string or API credentials, then hand each submission to a throwaway sandbox container with no network access and strict resource limits. The worker picks up jobs from a NATS JetStream queue rather than executing anything the API receives directly, and Headscale VPN ACLs prevent the worker from reaching the database even though it shares the network.

_Anyone architecting code-execution sandboxes can compare real setups like this one on daily.dev._

### Why would I run a Postgres database on the same server as my API instead of using a managed database service?

Running Postgres on the same box as the API eliminates network hop latency for queries and can cost far less than a managed Postgres instance, since the failure modes are already coupled anyway (if the server dies, the API is down regardless of database health). The tradeoff is that backups become the operator's own responsibility, handled here via a nightly pg_dump cron job shipped to Cloudflare R2.

_daily.dev surfaces tradeoff discussions like this for developers weighing self-hosted versus managed databases._

### Why choose Paddle over Stripe for a SaaS selling internationally as a solo developer?

Paddle acts as a merchant of record, meaning it is legally the seller and handles global sales tax and VAT, which matters for a solo developer avoiding tax filings across many countries. An additional practical reason is that Stripe is not available in Serbia, while Paddle is, making it the available option for a business run from there.

_Developers deciding between payment providers for global SaaS launches can find comparisons like this on daily.dev._

## Community discussion

Top comments from developers on daily.dev.

**@trevorsuna** · 5 upvotes

> Love the split here: buy auth and payments, own the core, and isolate untrusted code hard. Three small servers with clear jobs feel easier to reason about than a pile of managed services, imo.

**@ajaychoudhary80** · 0 upvotes

> Container isolation, network restrictions, and message queues make for a strong defense-in-depth approach.

## Similar posts on daily.dev

- [Scaling to 100k\+ Products: A Resilient .NET 10, K8s, and Next.js 15 Event-Driven Architecture](https://daily.dev/posts/scaling-to-100k-products-a-resilient-net-10-k8s-and-next-js-15-event-driven-architecture-w4juev2fb) · Medium · 17 upvotes · 0 comments
- [How I Built a KiloClaw Dashboard that Does Work for Me](https://daily.dev/posts/how-i-built-a-kiloclaw-dashboard-that-does-work-for-me-q6ltkomhz) · Kilo Blog · 62 upvotes · 2 comments
- [Learning Back-End Stack and Architecture by Building a User Analytics platform](https://daily.dev/posts/learning-back-end-stack-and-architecture-by-building-a-user-analytics-platform-mrwdm6rnm) · iO tech\_hub · 18 upvotes · 0 comments
- [Building Service Topology at Scale: Architecture, Challenges, and Lessons Learned](https://daily.dev/posts/building-service-topology-at-scale-architecture-challenges-and-lessons-learned-qptwmjvf7) · Netflix TechBlog · 26 upvotes · 0 comments

---

Tags: [#career](https://daily.dev/tags/career), [#.net](https://daily.dev/tags/.net), [#self-hosting](https://daily.dev/tags/self-hosting)

[View this post on daily.dev](https://daily.dev/posts/the-system-design-behind-my-new-saas-n2rai39sp)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"The System Design Behind My New SaaS","url":"https://daily.dev/posts/the-system-design-behind-my-new-saas-n2rai39sp","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/the-system-design-behind-my-new-saas-n2rai39sp"},"datePublished":"2026-07-24T20:01:06.285Z","dateModified":"2026-09-13T21:19:48.618Z","description":"A detailed walkthrough of the system design behind Katabench, a .NET coding platform that safely executes arbitrary C# code submitted by users. The...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/25ef2a3d05d444baebcca48f3cfffce3?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/25ef2a3d05d444baebcca48f3cfffce3?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Milan Jovanović","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Milan Jovanović","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/78d8abfb692746538410dee47f93e566","url":"https://daily.dev/sources/milanjovanovic"},"commentCount":6,"discussionUrl":"https://daily.dev/posts/the-system-design-behind-my-new-saas-n2rai39sp","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":49},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":6}],"keywords":"career,.net,self-hosting","timeRequired":"PT10M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Milan Jovanović","item":"https://daily.dev/sources/milanjovanovic"},{"@type":"ListItem","position":3,"name":"The System Design Behind My New SaaS"}]}
{"@context":"https://schema.org","@type":"WebPage","@id":"https://daily.dev/posts/the-system-design-behind-my-new-saas-n2rai39sp","comment":[{"@type":"Comment","text":"Love the split here: buy auth and payments, own the core, and isolate untrusted code hard. Three small servers with clear jobs feel easier to reason about than a pile of managed services, imo.","datePublished":"2026-07-27T01:40:15.010Z","url":"https://daily.dev/posts/n2RAI39sp#c-wPFzyv8fv","author":{"@type":"Person","name":"Trevor Suna","url":"https://daily.dev/trevorsuna","image":"https://media.daily.dev/image/upload/s--dZ7gXxpp--/f_auto/v1784081551/avatars/avatar_EMoP47rpuw8DNjhp6R1b6?_a=BAMAMicg0"},"interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":5}},{"@type":"Comment","text":"Container isolation, network restrictions, and message queues make for a strong defense-in-depth approach.","datePublished":"2026-07-27T02:55:53.576Z","url":"https://daily.dev/posts/n2RAI39sp#c-RRLa2mNmS","author":{"@type":"Person","name":"Ajay Choudhary","url":"https://daily.dev/ajaychoudhary80","image":"https://media.daily.dev/image/upload/s--WkX8wDW2--/f_auto/v1780989706/avatars/avatar_QNZlI2SgVnNSx5PSRpCVx?_a=BAMAMiWQ0"}}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/the-system-design-behind-my-new-saas-n2rai39sp#faq","mainEntity":[{"@type":"Question","name":"How can I safely run untrusted user-submitted code on my own servers instead of a managed sandbox service?","acceptedAnswer":{"@type":"Answer","text":"Isolate execution on a dedicated worker server with no database connection string or API credentials, then hand each submission to a throwaway sandbox container with no network access and strict resource limits. The worker picks up jobs from a NATS JetStream queue rather than executing anything the API receives directly, and Headscale VPN ACLs prevent the worker from reaching the database even though it shares the network. Anyone architecting code-execution sandboxes can compare real setups like this one on daily.dev."}},{"@type":"Question","name":"Why would I run a Postgres database on the same server as my API instead of using a managed database service?","acceptedAnswer":{"@type":"Answer","text":"Running Postgres on the same box as the API eliminates network hop latency for queries and can cost far less than a managed Postgres instance, since the failure modes are already coupled anyway (if the server dies, the API is down regardless of database health). The tradeoff is that backups become the operator's own responsibility, handled here via a nightly pg_dump cron job shipped to Cloudflare R2. daily.dev surfaces tradeoff discussions like this for developers weighing self-hosted versus managed databases."}},{"@type":"Question","name":"Why choose Paddle over Stripe for a SaaS selling internationally as a solo developer?","acceptedAnswer":{"@type":"Answer","text":"Paddle acts as a merchant of record, meaning it is legally the seller and handles global sales tax and VAT, which matters for a solo developer avoiding tax filings across many countries. An additional practical reason is that Stripe is not available in Serbia, while Paddle is, making it the available option for a business run from there. Developers deciding between payment providers for global SaaS launches can find comparisons like this on daily.dev."}}]}
```

