The Real Cost of a Tiny C Web App
Key takeaways
- C, CGI, and SQLite can remove the need to operate separate application and database servers.
- Traditional CGI starts a program for every request, trading simpler process management for repeated startup costs.
- Fewer dependencies do not eliminate memory bugs, authentication flaws, or other web vulnerabilities.
- Maintenance includes the code you write yourself and the components bundled into your executable.
A bookmark manager has a modest job: save links, display them, and delete the ones you no longer need. Even in 2026, C and CGI can be a reasonable way to keep the machinery behind it small. The interesting question is how much work actually disappears when you strip the stack down.
What CGI takes off your plate
Imagine a browser sending a request to a web server. The server launches a C executable, which reads from SQLite and returns HTML. That is enough architecture for a small, useful application.
CGI, the Common Gateway Interface, defines how a web server exchanges request and response data with an external program. It is a protocol boundary, not a programming language or framework. A C executable can handle web requests by accepting input and producing output in the expected format.
With traditional CGI, the server launches the program for each request. You do not have a persistent application process to keep running and manage.
You do, however, pay for startup and initialization every time. For a personal tool that gets occasional visits, that may be perfectly acceptable. For a busy service, you need to test it under realistic load.
A small executable is satisfying. It is not a performance benchmark.
SQLite and OpenBSD simplify specific jobs
SQLite runs inside the application, so you can use SQL and transactions without operating a separate database server. That removes a meaningful chunk of infrastructure from a small deployment.
The data still needs attention. Backups, recovery, and schema changes remain your responsibility. SQLite supports multiple readers, but writes proceed one writer at a time. The relevant question is how often requests need to write concurrently, alongside how many people use the app.
OpenBSD offers another useful layer: ways to restrict what a program can do.
Its pledge mechanism limits the system operations a program can use. unveil restricts which filesystem paths it can access and with what permissions. A bookmark manager can be limited to the files and operations it actually needs, helping contain the damage if a vulnerability is exploited.
Those restrictions need to match the program’s behavior. Merely running an application on OpenBSD does not automatically confine everything it does.
Each component removes a particular burden. None removes the need to understand the application.
The framework’s work becomes your work
Reducing external packages gives you fewer packages to track and update. That is a real benefit, but it does not establish that the application is safer overall.
C does not automatically guarantee memory safety. An incorrect length calculation can lead to writing beyond an allocated buffer. A program can also access memory after it has been freed. In an application processing outside input, those mistakes can become security vulnerabilities.
Removing a framework also means taking responsibility for work it previously handled: request parsing, input limits, error handling, and session management. Replacing a security-reviewed library with your own implementation shortens the dependency list while adding code you must review.
Then there are the familiar web problems. Concatenating user input into SQL can introduce SQL injection; parameter binding addresses that risk. Rendering a saved link title directly into HTML can allow script execution; escaping must match the output context.
Authentication still needs careful design and implementation, too.
Dependency reduction, memory safety, and privilege restrictions address different problems. They can complement each other, but you cannot count one as having solved the others.
Count the responsibilities you keep
This stack deserves consideration when the application has few features, changes infrequently, and has an operator comfortable with C and the operating system. A personal utility or a service for a limited group can fit that description well.
The calculation changes as login options and external integrations accumulate. More features mean more functionality to implement and validate yourself. Eventually, someone else may need to understand and modify the code, and that handoff belongs in the maintenance budget.
Even a single deployment binary carries ongoing obligations. If you bundle SQLite into the executable, incorporating a SQLite fix requires rebuilding and redeploying the application. Packaging a component does not retire it from maintenance.
The practical test is whether you can diagnose a failure and make a safe change. Package count tells you only part of that story.
C and CGI can give a small web app a simpler operating structure. The payoff depends on whether the responsibilities left in your hands are ones you can comfortably carry for years.
Comments
Loading comments...