---
title: "zwei und eins gmbh: simpler software, ready for AI agents"
description: "Swiss software architecture: we cut the cost of over-engineered web stacks and make your applications usable by AI agents."
url: https://zweiundeins.gmbh/en
language: en
---

Software architecture & agentic development

# Simpler software. *Ready for AI agents.*

We cut the cost of over-engineered web stacks and make your applications usable by AI agents. One process on one server, one SQLite file, HTML over the wire.

[Get in touch](https://zweiundeins.gmbh/en#contact) [How we work](https://zweiundeins.gmbh/en#approach)

[**8.3×** faster on mobile · **27×** less data · **$20** a year to host · Same app, built twice: read the benchmark →](https://zweiundeins.gmbh/en/blog/spa-vs-hypermedia-real-world-performance-under-load)

[**My stack is too expensive** · Cloud bills, a platform team, a frontend nobody wants to touch. We turn that into one server and one database.](https://zweiundeins.gmbh/en#approach) [**I want my app to work with AI agents** · Let your users work with your product from Claude, ChatGPT or Copilot, safely.](https://zweiundeins.gmbh/en#llm-ready)

Approach

## From cloud complexity to one binary on one server.

Most web apps don't need a distributed system. They need a fast server, a reliable database and HTML. Everything else is cost.

### The usual stack 10 parts

- Eight bills that grow with usage
- A platform team of its own to run it
- 592 npm packages to keep patched

### Our stack 3 parts

- No frontend build, no cold starts, no vendor lock-in
- Predictable cost: one server at a fixed price, not usage fees
- Small enough for one person, or one agent, to understand

### This page, live from its server

This site is built the way we describe: one Go binary on one server. While you watch, these numbers come from the server once a second, as HTML over one compressed stream.

[Our principles, and the objections we hear →](https://zweiundeins.gmbh/en/approach)

LLM-ready

## Your app, usable from any AI assistant.

Your customers already ask ChatGPT and Claude to do their work. We build an MCP server in front of your existing API so they can, with you in control of what an agent may read and write.

AI agent *Claude, ChatGPT, Copilot*

Model Context Protocol

**MCP server**  
read tools · write tools only in write mode · every write previewed before it runs

your existing API

your application

### MCP servers we have built

- **cashctrl-mcp** · Accounting
  
  18 read tools over all 376 endpoints of the CashCtrl accounting API, four write tools that only exist in write mode and preview every change before it is made.
  
  [Open source on GitHub →](https://github.com/zweiundeins/cashctrl-mcp)
- **Libretto** · Vehicles
  
  Our SaaS for vehicle costs: 8 tools on Swiss vehicle data without signing in, and 22 tools for your own garage behind OAuth, 14 of them writing. Every call lands in the audit log.
  
  [libretto.ch →](https://libretto.ch)
- **PHP CMS** · Website
  
  43 tools with which agents run websites: content in every language, files, navigation, link checks. With a read-only key, or a writer role that can't delete.

**cashctrl-mcp: Accounting**

1. Which customer invoices from September are still unpaid?
2. cashctrl **list\_open\_invoices** { type: "sales", from: "2026-09-01", to: "2026-09-30" } → 4 open orders
3. Four September invoices are open, CHF 4,180 in total. The oldest is Meier AG, due 12 days ago. Shall I create a reminder?
4. Yes, for the overdue one.
5. cashctrl **create\_record** { resource: "order", … } → preview
6. cashctrl shows a preview
   
   Reminder to Meier AG for CHF 1,240.00, due in 10 days. Nothing is written until you confirm.
   
   Confirmed
7. The reminder is in CashCtrl.

Illustration using cashctrl-mcp's real tools.

**Libretto: Vehicles**

1. What’s coming up for my cars?
2. libretto-garage **upcoming** → 2 dates
3. Two dates: the Saab 900 S is due for its inspection on 19 October, and the 530d’s emissions service on 3 December.
4. Serviced the 530d today, 221,150 km, 340 francs: oil and filter.
5. libretto-garage **add\_entry** → recorded
6. libretto-garage asks you to confirm
   
   BMW 530d Touring xDrive: CHF 340.00 on 2026-09-22 (werkstatt): Service: oil and oil filter \[resets: oil]. Record this?
   
   Confirmed
7. Recorded. The oil-change interval starts over from today.

Re-enacted from a real session with Libretto's demo garage.

**PHP CMS: Website**

1. Please publish the Kanban post, in German and English, with the cover image.
2. cms **upload\_file** { folder: "upload/blog" } → 20261008-kanban-hero.jpg
3. cms **create\_record** { table: "blog", … } → id 3
4. cms **update\_multilingual** { lang: "de", … }, { lang: "en", … } → 2 languages
5. cms **link\_check** → no dead links
6. The post is live, in both languages and with its cover image. The link check finds no dead links.

After a real session: how we published a post this week.

Services

## Four ways we work with you.

01

### Architecture audit

One to two weeks: a code review, a workshop and written findings on where your cost and complexity come from, and what to cut first.

02

### Simplify & migrate

Off microservices, serverless or a hyperscaler, step by step, without a big-bang rewrite.

03

### Make your app LLM-ready

MCP server, OpenAPI spec, typed SDK and a permission model your security team can sign off.

04

### Agentic development

We build with your team using coding agents, and show them how to keep quality under control.

Cases

## Measured, not claimed.

Three of our own builds, with the source and the raw data on GitHub.

Collaborative app · Go

### [A live Kanban board, without a single-page app](https://zweiundeins.gmbh/en/blog/spa-vs-hypermedia-a-collaborative-kanban-board-measured-against-planka)

Several people drag cards on the same board, rendered on the server: one Go binary, one SQLite file, HTML over SSE. Measured against PLANKA (React, PostgreSQL) on a slowed phone.

27×

sooner on screen

2.8×

sooner a confirmed move

1

process instead of 18

Read the measurements →

AI chat app · PHP

### [The same app, built twice](https://zweiundeins.gmbh/en/blog/spa-vs-hypermedia-real-world-performance-under-load)

We rebuilt Vercel's Next.js AI chatbot as a server-rendered hypermedia app and measured both on a mid-range phone over slow 4G.

8.3×

faster to interactive

27×

less data on page load

33×

fewer dependencies

Read the measurements →

Real-time multiplayer · php-via

### [Multiplayer Game of Life, without app JavaScript](https://zweiundeins.gmbh/en/blog/multiplayer-game-of-life-with-php-and-sse)

A shared board of 2,500 cells, pushed to every player five times a second over one compressed SSE stream, from a single PHP process on our own framework, php-via.

~500×

compression on the stream

127 KB

for two minutes of play, not 60 MB

0

lines of application JavaScript

Play it and read how →

Open Source

## The approach, in public code.

### [lith](https://github.com/zweiundeins/lith)

Runtime for Go apps on SQLite and Datastar: one writer applies every write in order, each changed view renders once per tick for everyone who has it open, and goes out compressed over SSE. This site runs on it too.

Go · SQLite · Datastar

### [starbase](https://github.com/zweiundeins/starbase)

Gallery of Datastar web components. Go, templ, SQLite, CQRS: the stack we recommend, end to end.

Go · 31 stars

### [kanban](https://github.com/zweiundeins/kanban)

Collaborative Kanban board: one Go binary, SQLite, Datastar. Measured against PLANKA, with every script and all raw data.

Go · case study

### [cashctrl-mcp](https://github.com/zweiundeins/cashctrl-mcp)

MCP server for the Swiss accounting system CashCtrl. 376 endpoints, read-only unless write mode is on, writes previewed.

TypeScript · MCP · 79 downloads

### [nfsen-ng](https://github.com/mbolli/nfsen-ng)

Responsive NetFlow visualiser on top of nfdump. Our most-starred project.

PHP · 283 stars · 25k Docker pulls

### [php-via](https://github.com/mbolli/php-via)

Real-time engine for reactive web apps in PHP on Swoole and Datastar. Runs the Game of Life from our blog.

PHP · 90 stars · 755 downloads

### [ai-chatbot](https://github.com/mbolli/ai-chatbot)

Vercel's Next.js AI chatbot, rebuilt in PHP with Swoole and Datastar: the app behind our measurements, with the raw data.

PHP · case study

### Also on Packagist and npm

- [php-geobuf](https://packagist.org/packages/mbolli/php-geobuf)
  
  Geobuf, a compact format for geodata, in PHP.
  
  43,934 downloads · Packagist
- [php-ron](https://packagist.org/packages/mbolli/php-ron)
  
  RON in PHP: JSON's value model with a lighter syntax, for people and LLMs.
  
  2,777 downloads · Packagist
- [datastar-attribute-on-keys](https://www.npmjs.com/package/@mbolli/datastar-attribute-on-keys)
  
  Datastar plugin that binds key combinations to actions.
  
  1,285 downloads · npm
- [datastar-attribute-prop](https://www.npmjs.com/package/@mbolli/datastar-attribute-prop)
  
  Datastar plugin that keeps element properties in sync with signals.
  
  1,017 downloads · npm
- [cashctrl-ts-sdk](https://www.npmjs.com/package/@zweiundeins/cashctrl-ts-sdk)
  
  Typed TypeScript client for all 376 endpoints of the CashCtrl API, with an OpenAPI 3.1 spec.
  
  690 downloads · npm

[All projects on GitHub →](https://github.com/zweiundeins)

Blog

## Long reads, with the raw data.

Tech Deep Dive · 20 October 2026 · 19 min read

### [lith: The Runtime Under Our Go Apps](https://zweiundeins.gmbh/en/blog/lith-the-runtime-under-our-go-apps)

lith is the open-source runtime under our multiplayer Go apps on SQLite and Datastar: one writer, one render per tick, compressed HTML streams, all measured.

Case study · 8 October 2026 · 13 min read

### [SPA vs. Hypermedia: A Collaborative Kanban Board Measured Against PLANKA](https://zweiundeins.gmbh/en/blog/spa-vs-hypermedia-a-collaborative-kanban-board-measured-against-planka)

We built a Kanban board on which several people drag cards at the same time, rendered entirely on the server, and measured it against PLANKA on a slowed phone.

[All articles →](https://zweiundeins.gmbh/en/blog)

Objections

## Fair questions.

What does this bring us as a business?

Lower development costs, because there is less architecture to build and keep in sync. Lower running costs, because one server replaces a cloud of metered services. Faster changes, because logic and state live in one place. And predictable performance, because the server decides how much it sends.

Isn't this old-fashioned?

Server-rendered HTML is how the web started. What's new is streaming updates over a single SSE connection, so the page feels real-time without shipping your application state to the browser.

Won't it feel slow without an SPA?

We measured it twice on a mid-range phone over slow 4G. Our version of the same chat app became interactive 8.3 times sooner than the Next.js original, and on our Kanban board a dragged card is confirmed by the server after 253 ms, where PLANKA, built with React, needs 712 ms.

Does SQLite scale?

With a single writer, performance is almost never the issue. All writes go through one connection, one after the other, so they never wait on each other's locks, and reads run alongside them without waiting. The database is a file next to the application, so a query costs no network round trip. What a single writer rules out is many processes writing at once, and the architecture is built not to need that. The writer of our Kanban board handles about 13,800 moves a second with 200 people moving cards at once.

What if the one server goes down?

systemd restarts a crashed process within seconds. Litestream copies every change to object storage in Switzerland about a second later, and a daily test restore checks that the copy works. If the server itself fails, a new one restores the data as it starts. That is how our SaaS Libretto runs. Until the new server is up, the app is down. For most business apps that is a fair price for not running a cluster; if it isn't for yours, we'll tell you before we start.

What about offline-first?

For most business apps it's the wrong default. Offline-first means optimistic updates: the browser shows a result before the server has accepted it, and has to take it back when the server refuses. That moves conflict handling into every client. We keep the server in charge and show honestly what it has confirmed. Where real offline work is essential, a native app is the better tool.

Aren't we locking ourselves in to you?

Go, SQLite and systemd are boring, open and widely known. The code is yours, and any Go developer can take it over.

Is it safe to let an AI agent write to our system?

Only if you decide it is. Our MCP servers are read-only by default. Write tools only exist in write mode, and every write is shown as a preview until someone confirms it.

Will AI-written code become unmaintainable?

It will in a sprawling architecture. In a small codebase with one binary and one database, a reviewer can still read every change, and that is the point.

[All principles and objections →](https://zweiundeins.gmbh/en/approach)

![Portrait of Michael Bolli](https://zweiundeins.gmbh/s/gen/img/michael-359.d0f1641efb.webp)

About

## Problem solvers, not a dev shop.

Behind zwei und eins gmbh is Michael Bolli. For over 20 years he has built and looked after web applications, with a focus on architecture, performance and systems that stay maintainable.

He works without unnecessary framework layers, joins existing systems and teams quickly, and maintains open-source projects such as nfsen-ng and php-via.

Aarberg, Switzerland · [github.com/mbolli](https://github.com/mbolli) · [LinkedIn](https://linkedin.com/in/mbolli)

Contact

## Tell us what's too complicated.

### Prefer email?

- [info@zweiundeins.gmbh](mailto:info@zweiundeins.gmbh)
- zwei und eins gmbh  
  Kistlerweg 1  
  3270 Aarberg, Switzerland
