Skip to main content

5 posts tagged with "devops"

View All Tags

· 7 min read
Arkin Eliezer Julijanto

Meta description: Why backward compatibility matters more than ever. From Wine to DOSBox, discover how the Linux ecosystem preserves access to decades-old software while modern development races forward.

The Myth of Obsolescence​

In tech, we love the new. New frameworks, new languages, new paradigms. The unspoken assumption: old software dies, and that's fine.

But it's not fine. Every day, businesses run critical operations on Windows 95-era point-of-sale systems. Industrial equipment controllers speak protocols from the 1990s. Government databases rely on applications whose source code was lost when the original developer retired in 2003.

This isn't incompetence. It's backward compatibility — the unglamorous but essential engineering discipline that keeps the digital world from fracturing every decade.

A recent discussion on Hacker News, titled "Windows 9x Subsystem for Linux," sparked 226 comments and 957 points. While the specific project referenced may have been satirical, the conversation it triggered revealed something deeper: the enduring need to run legacy Windows applications on modern systems.

The Linux Ecosystem's Answer​

Linux, long criticized for fragmentation, has actually built the most comprehensive toolkit for legacy compatibility. Here's what exists today:

Wine: The Windows Compatibility Layer​

Wine (Wine Is Not an Emulator) has been running Windows applications on Linux since 1993. It's not emulation — it translates Windows API calls into POSIX calls on the fly. No Windows license required, no virtual machine overhead.

What works surprisingly well:

  • Office 97-2003 documents and basic apps
  • Older games (StarCraft, Diablo II, SimCity 2000)
  • Business applications from the Windows 9x/XP era
  • Some specialized engineering and scientific software

What doesn't:

  • Modern Windows apps with heavy .NET or UWP dependencies
  • Games with aggressive anti-cheat systems
  • Anything requiring specific Windows drivers

Wine's AppDB (Application Database) crowd-sources compatibility information for thousands of applications. If you need to run a specific Windows 95 app, someone has probably tried it and documented what works.

DOSBox: For the DOS Era​

Before Windows, there was DOS. DOSBox, originally designed for gaming, has become the de facto standard for running DOS applications on modern systems. It's used not just by retro gamers but by:

  • Industrial equipment manufacturers documenting legacy controllers
  • Archivists preserving historical software
  • Researchers analyzing old scientific software

DOSBox is included in major Linux distributions and runs with near-perfect accuracy for DOS-era applications.

ReactOS: The Windows Clone​

ReactOS aims to be a binary-compatible, open-source reimplementation of Windows NT. It's not running on Linux — it's its own operating system — but it represents the most ambitious attempt at Windows compatibility.

After 20+ years of development, ReactOS can boot and run many Windows XP-era applications. It's not production-ready for most use cases, but it demonstrates what's possible when a community commits to long-term compatibility work.

Why This Matters in 2026​

The Business Case​

Imagine you're a mid-sized manufacturing company. Your production line runs on a Windows 98-based SCADA system. The original vendor went out of business in 2005. The software controls 12 machines, each worth $200,000.

Options:

  1. Replace everything: $5M+, 6 months downtime, retrain staff
  2. Keep Windows 98 running: Security nightmare, no hardware support
  3. Use Wine/DOSBox on modern Linux: Low cost, modern hardware, gradual migration

The third option is often the only practical one. This isn't about being lazy — it's about business continuity.

The Preserved Knowledge Problem​

Software is knowledge encoded. When you lose access to old software, you lose the knowledge it contains:

  • Scientific data formats: Can you read a proprietary 1995 microscopy data file?
  • Historical records: Court cases, medical records, financial data
  • Cultural artifacts: Video games, creative software, early digital art

Archivists and historians increasingly rely on compatibility layers to access digital heritage. When the Library of Congress preserves software, they're preserving not just code, but the culture and knowledge it represents.

The Developer's Dilemma​

As a developer, you will encounter legacy systems. They are not failures — they are survivors. They solved a problem well enough to keep running for decades.

Understanding how to work with them is a superpower:

  • You become the person who can "fix the old thing"
  • You learn patterns that have stood the test of time
  • You develop humility about what "modern" means

The Paradox of Progress​

We've built a tech industry obsessed with velocity. Shipping fast, breaking things, moving on to the next framework. This energy has driven incredible innovation.

But the cost is fragmentation. Every new paradigm breaks compatibility with the old one. New APIs, new package managers, new deployment targets. The entropy is real.

Meanwhile, the boring projects — Wine, DOSBox, libvips, ImageMagick, FFmpeg — keep the digital world from collapsing under its own weight. They are the infrastructure of continuity.

When you build something today, ask yourself: What happens to this in 10 years? 20 years?

  • Is the data format open and documented?
  • Are the dependencies replaceable?
  • Could someone run this without your original build environment?

The best software is built with an eye on both the present and the future.

Practical Takeaways​

If you're dealing with legacy Windows apps:

  1. Check Wine's AppDB first — someone has probably documented your use case
  2. Try DOSBox for DOS-era applications
  3. Consider virtualization (QEMU/KVM) as a fallback
  4. Document your setup — the next person will thank you

If you're building new software:

  1. Use standard, documented formats (CSV, SQLite, PNG, not custom binaries)
  2. Avoid hard dependencies on cloud services
  3. Include export/migration paths
  4. Write tests that verify backward compatibility

If you're a startup founder:

  1. Assume you'll need to integrate with legacy systems
  2. Plan for data portability from day one
  3. Budget time for compatibility testing
  4. Respect that your customers may have decades of accumulated software debt

The Future of Compatibility​

The next frontier is AI-assisted compatibility. Imagine an agent that:

  • Automatically generates Wine configuration files
  • Translates legacy APIs to modern ones
  • Documents the quirks of old software as it encounters them

We're seeing early versions of this. But the core truth remains: compatibility is a human problem that requires human investment.

Wine has been maintained for 30 years by volunteers. DOSBox for 20. These are labors of love, not commercial products. Their persistence is a reminder that some problems are too important to leave to market forces alone.

FAQ​

Q: Can Wine run modern Windows applications? A: Generally, no. Wine excels at Windows 9x/XP era applications. Modern apps with .NET, UWP, or heavy DirectX 12 dependencies typically don't work. For those, virtualization (running actual Windows in a VM) is more reliable.

Q: Is running legacy Windows software on Linux secure? A: It depends. Wine/DOSBox apps are sandboxed to some extent but don't have the same security boundaries as modern Linux applications. Treat them as untrusted — run them in containers or separate users, limit network access, and don't grant them unnecessary permissions.

Q: Why not just use virtualization? A: Virtualization (VMware, QEMU, VirtualBox) requires a Windows license and has higher overhead. Wine/DOSBox run directly on Linux with near-native performance for supported applications. Use virtualization when Wine compatibility is insufficient.

Q: How do I preserve old software I can't run anymore? A: 1) Archive the original install media and any serial numbers, 2) Document the exact hardware/software environment it ran on, 3) Save virtual machine snapshots, 4) Consider contributing to projects like the Internet Archive's software collection.

Q: Is ReactOS ready for production use? A: Not yet. While ReactOS can run many Windows XP-era applications, it's still considered alpha-quality software. It's useful for testing and experimentation, but not for mission-critical systems. Keep an eye on it — it's improving steadily.

About the Author​

Arkin Julijanto is a startup founder and developer building Orbits Studio. He writes about software architecture, developer tooling, and the intersection of modern and legacy systems at arkin-dev.com.

· 7 min read
Arkin Eliezer Julijanto

Meta Description: Vercel confirmed a security breach via third-party OAuth compromise. Here's what every developer and founder needs to know about protecting their secrets and supply chain attacks.

The Wake-Up Call Every Founder Needed​

On April 19, 2026, Vercel—one of the most critical infrastructure platforms for modern web development—disclosed a security breach that should send shivers down every founder's spine. The attack wasn't some sophisticated zero-day exploit. It was a textbook supply-chain attack via a compromised OAuth application.

Think about it: one compromised Google Workspace account at a third-party AI tool (Context.ai) led to unauthorized access to Vercel's internal systems. The attacker didn't need to break Vercel's encryption or bypass their defenses—they walked in through a side door that no one thought to lock.

If you're deploying on Vercel, running a startup, or managing any cloud infrastructure, you need to understand what happened, why it matters, and what you should do right now.

How the Attack Unfolded: A Supply Chain Nightmare​

The breach began when a Vercel employee's Google Workspace account was compromised through Context.ai, a third-party AI platform. The attacker gained access via a malicious OAuth application:

OAuth App: 110671459871-30f1spbu0hptbs60cb4vsmv79i7bbvqj.apps.googleusercontent.com

From there, the attacker escalated their access within Vercel's internal systems. Here's where it gets interesting: they discovered environment variables that weren't marked as "sensitive" in Vercel's system.

Vercel has a feature to designate environment variables as sensitive, which ensures they're encrypted at rest. But variables marked as non-sensitive—the ones intended for configuration data—were stored unencrypted. The attacker enumerated these variables and used them to gain further access.

This is a classic privilege escalation attack disguised as a configuration issue. The problem wasn't that Vercel failed to encrypt sensitive data—they did. The problem was that what developers thought was "non-sensitive" configuration data turned out to be a pathway to deeper access.

Why This Attack Is So Dangerous​

This breach exposes a fundamental vulnerability in how we think about third-party integrations and OAuth security:

1. The Trust Chain Problem

We implicitly trust OAuth applications. When we click "Authorize" on a third-party tool, we're granting access to our Google Workspace, GitHub, or other accounts. If that tool is compromised, the attacker inherits all the access we've granted.

2. The Configuration Blind Spot

Developers often treat environment variables as either "sensitive" (API keys, database passwords) or "non-sensitive" (API endpoints, feature flags). But configuration data can be just as valuable—internal service URLs, project identifiers, and deployment targets can reveal a system's architecture.

3. The Supply Chain Ripple Effect

A breach at one third-party vendor (Context.ai) compromised a major platform (Vercel), which potentially exposed countless applications deployed by Vercel's customers. The attack surface expands exponentially through the supply chain.

What You Should Do Right Now​

If you're deploying on Vercel or using similar cloud platforms, here's your immediate action list:

1. Rotate All Secrets​

This is non-negotiable. Even if Vercel says you're not affected, assume you might be. Rotate:

  • Database credentials
  • API keys (Stripe, OpenAI, Twilio, etc.)
  • OAuth tokens
  • Private keys
  • Any secret stored in environment variables

2. Review Your OAuth Permissions​

Go to your Google Workspace, GitHub, and other OAuth providers. Review every third-party application with access. Revoke anything you don't recognize or no longer use.

3. Audit Your Environment Variables​

Log into Vercel (or your platform of choice) and review every environment variable:

  • Mark anything that could be used for access as "sensitive"
  • Remove unused variables
  • Audit the values—look for internal URLs, project IDs, or identifiers that could aid an attacker

4. Enable Vercel's Sensitive Variable Feature​

Vercel has a feature that encrypts sensitive environment variables at rest. Use it. For any variable that contains secrets, authentication data, or internal infrastructure details, mark it as sensitive.

5. Implement Secret Rotation Policies​

Don't wait for a breach. Rotate secrets regularly—every 90 days for high-risk credentials, every 6 months for others. Automate this where possible.

The Bigger Lesson: Defense in Depth Is Non-Negotiable​

Vercel did a lot of things right: they had encryption for sensitive data, defense-in-depth mechanisms, and a rapid incident response. But the attack still succeeded because one layer of defense—OAuth application security—was outsourced to a third party.

This is why security best practices matter:

  • Zero Trust: Never assume any component is safe, even if it's from a trusted vendor
  • Least Privilege: Grant the minimum access necessary
  • Audit Regularly: You can't protect what you don't know about
  • Assume Breach: Design your systems assuming an attacker already has some access

What Vercel Is Doing Right​

To Vercel's credit, they've handled this well:

  • Immediate disclosure and transparent communication
  • Clear guidance for affected customers
  • Rolling out security updates (new environment variable overview, improved sensitive variable management)
  • Confirmation that open-source projects (Next.js, Turbopack) remain safe

This is how security incidents should be handled. No hiding, no deflection—just facts, guidance, and action.

The Future of Cloud Security​

This breach isn't unique to Vercel. It could happen to any platform that relies on OAuth integrations. As we build more interconnected systems, the attack surface grows.

The future of cloud security lies in:

  • OAuth hardening: More granular permissions, better auditing, automated revocation
  • Secret management: Dedicated secret managers (AWS Secrets Manager, HashiCorp Vault) instead of environment variables
  • Supply chain security: Security reviews for every third-party integration
  • Automated rotation: Tools that automatically rotate secrets before they can be exploited

Conclusion​

The Vercel breach is a wake-up call, not a reason to abandon cloud development. The platform remains one of the best options for deploying modern applications—but this incident reminds us that security is a process, not a product.

Rotate your secrets. Review your OAuth apps. Audit your environment variables. And never assume that "non-sensitive" means "harmless."

The attacker didn't exploit a bug in Vercel's code—they exploited a blind spot in how we think about security. Close that blind spot before someone else walks through it.

FAQ Section​

Q: Was my Vercel project affected by the breach? A: Vercel states that only a "limited subset of customers" were affected. However, if you're not sure, the safest approach is to rotate all your secrets as a precaution.

Q: What's the difference between sensitive and non-sensitive environment variables in Vercel? A: Sensitive environment variables are encrypted at rest and have additional protections. Non-sensitive variables are stored unencrypted and intended for configuration data—but they can still contain valuable information for attackers.

Q: How often should I rotate my API keys and secrets? A: High-risk credentials (database passwords, production API keys) should be rotated every 90 days. Lower-risk credentials can be rotated every 6 months. Automate this process where possible.

Q: Is it safe to keep using Vercel after this breach? A: Yes. Vercel has responded transparently, patched the vulnerability, and implemented additional security measures. No platform is immune to attacks—what matters is how they respond, and Vercel's response has been exemplary.

Q: How can I check if a malicious OAuth app has access to my accounts? A: Go to your Google Workspace admin console, GitHub settings, or other OAuth providers. Look for applications you don't recognize or no longer use. Vercel has published the specific OAuth app ID to watch for: 110671459871-30f1spbu0hptbs60cb4vsmv79i7bbvqj.apps.googleusercontent.com

About the Author​

Arkin Julijanto is a founder and full-stack developer building Orbits Studio, a clip farming marketplace connecting creators with brands. He writes about development, security, and the founder journey. You can find him on Twitter @Arkinej.

· 9 min read
Arkin Eliezer Julijanto

Meta Description: Claude Code Routines let you automate repetitive development tasks with scheduled jobs, API triggers, and GitHub webhooks. Here's how to build autonomous coding workflows that run 24/7.

Beyond Chat: When Your AI Agent Needs to Run on Autopilot​

Chat-based AI coding has transformed how developers work. But there's a limit to what you can do through conversational prompts alone. Sometimes you need work to happen while you're asleep — or while you're focused on something else entirely.

That's what Claude Code Routines are for: pre-configured Claude Code sessions that run automatically, triggered by schedules, API calls, or GitHub events. They execute on Anthropic-managed cloud infrastructure, so they keep working when your laptop is closed.

The release of Routines signals a broader shift in AI-assisted development: moving from interactive assistance to agentic automation. Instead of asking Claude to do something, you configure Claude to do it repeatedly, on its own schedule, without human intervention.

What Are Claude Code Routines?​

A Routine is a saved Claude Code configuration that includes:

  • A prompt defining the task
  • One or more GitHub repositories to work in
  • A set of MCP connectors for external services
  • One or more triggers that start the routine

When a trigger fires, Claude spins up a new cloud session, executes the prompt against the specified repositories, and creates a session record you can review later. It's like saving a perfect coding prompt and having Claude run it for you whenever you need.

Three Trigger Types​

Scheduled: Run on a recurring cadence — hourly, daily, weekdays, weekly, or custom cron intervals. Perfect for periodic maintenance tasks.

API: Trigger on demand with an HTTP POST to a dedicated endpoint. Use this to wire Claude Code into alerting systems, deploy pipelines, or internal tools.

GitHub: React to repository events like pull requests, pushes, or releases. Enables automated code reviews, PR triage, or synchronized library updates.

Key Capabilities​

  • Runs autonomously with no approval prompts
  • Can execute shell commands and use skills committed to repositories
  • Connects to external services via MCP (Slack, Linear, Google Drive, etc.)
  • Creates claude/-prefixed branches for its changes
  • Each run creates a session you can review or continue manually

What Can You Automate with Routines?​

The use cases are still emerging, but the documentation highlights several compelling patterns:

Backlog Maintenance​

A schedule trigger runs every weeknight, reading issues opened since the last run, applying labels based on the area of code, assigning owners, and posting a summary to Slack. Your team starts the day with a groomed queue instead of a messy backlog.

Alert Triage​

Your monitoring tool calls the routine's API endpoint when an error threshold is crossed. The routine pulls the stack trace, correlates it with recent commits, and opens a draft PR with a proposed fix. On-call reviews the PR instead of starting from a blank terminal.

Bespoke Code Review​

A GitHub trigger runs on pull_request.opened. The routine applies your team's own review checklist, leaves inline comments for security, performance, and style issues, and adds a summary comment so human reviewers can focus on design instead of mechanical checks.

Deploy Verification​

Your CD pipeline calls the routine's API endpoint after each production deploy. The routine runs smoke checks, scans error logs for regressions, and posts a go/no-go to your release channel before the deploy window closes.

Documentation Drift Detection​

A schedule trigger runs weekly, scanning merged PRs since the last run, flagging documentation that references changed APIs, and opening update PRs against the docs repository.

Cross-Language Library Ports​

A GitHub trigger runs on merged PRs in one SDK repository, ports the change to a parallel SDK in another language, and opens a matching PR — keeping multiple language implementations in sync without human re-implementation.

These patterns have something in common: they're unattended, repeatable, and tied to a clear outcome. That's the sweet spot for Routines.

How to Create a Routine​

From the Web Interface​

  1. Visit claude.ai/code/routines and click New routine
  2. Name the routine and write the prompt — this is the most important part. The routine runs autonomously, so the prompt must be self-contained and explicit about what to do and what success looks like
  3. Select one or more GitHub repositories. Claude clones them from the default branch and creates claude/-prefixed branches for changes
  4. Pick a cloud environment that controls network access, environment variables, and setup scripts
  5. Configure triggers — you can combine schedule, API, and GitHub triggers on a single routine
  6. Review connectors — remove any MCP connectors the routine doesn't need
  7. Click Create. The routine runs the next time a trigger matches

From the CLI​

Run /schedule in any session to create a scheduled routine conversationally. You can also pass a description directly: /schedule daily PR review at 9am.

The CLI creates scheduled routines only. To add API or GitHub triggers, edit the routine on the web. The CLI also supports managing existing routines with /schedule list, /schedule update, and /schedule run.

Key Configuration Details​

  • Prompts must be self-contained: The routine runs without you, so the prompt needs to explain everything — what to look for, how to decide, what to output
  • Scoping matters: What a routine can reach is determined by the repositories you select, environment variables, and connectors. Scope each to what the routine actually needs
  • Branch behavior: Claude creates claude/-prefixed branches by default. Enable "Allow unrestricted branch pushes" if the routine needs to push to other branches
  • Identity: Anything a routine does through your connected GitHub or connectors appears as you — commits carry your GitHub user, Slack messages use your linked account

Trigger Types in Depth​

Schedule Triggers​

Preset frequencies: hourly, daily, weekdays, weekly. Times are entered in your local timezone and converted automatically.

For custom intervals (every two hours, first of each month), pick the closest preset in the web form, then use /schedule update in the CLI to set a specific cron expression. The minimum interval is one hour.

Runs may start a few minutes after the scheduled time due to stagger, but the offset is consistent for each routine.

API Triggers​

Each routine gets a dedicated HTTP endpoint. POSTing with a bearer token starts a new session and returns a session URL you can open to watch the run in real time.

The request body accepts an optional text field for run-specific context (alert body, failing log, etc.). This is passed to the routine alongside its saved prompt as freeform text.

curl -X POST https://api.anthropic.com/v1/claude_code/routines/trig_XXXX/fire \
-H "Authorization: Bearer sk-ant-oat01-xxxxx" \
-H "anthropic-beta: experimental-cc-routine-2026-04-01" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{"text": "Sentry alert SEN-4521 fired in prod. Stack trace attached."}'

Each routine has its own token, scoped to triggering that routine only. Tokens are shown once during generation — store them securely in your alerting tool's secret store.

Note: The API ships under an experimental beta header. Breaking changes will ship behind new dated headers, with the two most recent versions supported for migration time.

GitHub Triggers​

A GitHub trigger starts a new session automatically when a matching event occurs. Each matching event fires its own session.

You'll need to install the Claude GitHub App on the repository you want to subscribe to. The trigger setup prompts you to install it if needed.

Important: During research preview, GitHub webhook events are subject to per-routine and per-account hourly caps. Events beyond the limit are dropped until the window resets.

Security and Scoping Considerations​

Routines run autonomously with no approval prompts. This means you need to think carefully about:

  • Repository access: Only select repositories the routine actually needs
  • Environment variables: Provide only the secrets and keys required for the task
  • Network access: Configure the appropriate level of internet access
  • Connectors: Include only the MCP connectors the routine uses

Anything a routine does appears as you — commits carry your GitHub user, connector actions use your linked accounts. Treat routine prompts like production code: clear instructions, error handling, and verification steps.

The Bigger Picture: From Assistants to Agents​

Routines represent an evolution in AI-assisted development. They move us from:

  • Interactive → Autonomous: Claude does work while you're away
  • One-off → Repeatable: Configure once, run forever
  • Task-based → Workflow-based: Entire processes, not just individual actions

This is the direction the industry is heading. Tools like Plain (a Python framework built for agents) and the rise of MCP connectors all point toward a future where AI agents are first-class members of development teams — not just assistants in the IDE, but autonomous workers in the CI/CD pipeline.

The challenge shifts from "how do I get Claude to help me with this?" to "how do I design reliable, trustworthy autonomous workflows?" Prompts become code. Testing becomes crucial. Monitoring and observability matter.

Routines are early days — the feature is in research preview with limits that may change. But they're a clear signal of where AI-assisted development is going.

FAQ​

Q: Do Claude Code Routines require a paid plan? A: Yes, Routines are available on Pro, Max, Team, and Enterprise plans with Claude Code on the web enabled. They're not available on free plans.

Q: Can I share routines with my team? A: During research preview, routines belong to your individual claude.ai account. They're not shared with teammates. Each team member would need to create their own routine, or you'd need to coordinate using shared prompts and configurations.

Q: What happens if a routine fails? A: Each routine run creates a session you can review. If a routine fails or produces unexpected results, you can open the session URL to see what happened, review changes, and continue the conversation manually. You should also add error handling and verification steps to your routine prompts.

Q: Are there limits on how often routines can run? A: Yes, during research preview there are per-routine and per-account hourly limits. The specific limits depend on your plan and are visible at claude.ai/code/routines. Events beyond the limit are dropped until the window resets.

Q: Can routines run concurrently? A: Yes, each trigger event starts its own independent session. A single routine can have multiple sessions running simultaneously if multiple triggers fire in quick succession.

· 8 min read
Arkin Eliezer Julijanto

Meta Description: A founder runs multiple profitable SaaS companies spending just $20/month on infrastructure. Here's the lean tech stack playbook — single VPS, Go, SQLite, and local AI.

The Bootstrapper's Dilemma​

Here's a story that sounds familiar: a founder walks into a pitch meeting. They have real users, real MRR, real product traction. The VC's response? "What do you even need funding for?"

That's exactly what happened to Steve Hanov — the creator of websequencediagrams.com and several niche SaaS products. His costs are so low that VCs can't figure out what to fund. And that's the point.

In 2026, the default startup playbook says: spin up AWS, provision EKS clusters, configure RDS instances, set up NAT Gateways, and accidentally burn $300/month before your first user even loads the landing page. The lean playbook says: rent a $5 VPS, compile a static binary, ship it.

One approach buys you a maze of managed services. The other buys you infinite runway.

The $20/Month Stack, Deconstructed​

Hanov's approach isn't about being cheap for its own sake. It's about keeping the architecture so simple that you spend your time solving user problems instead of debugging infrastructure. Here's what the stack looks like:

One Server, One Binary​

No Kubernetes. No container orchestration. No microservices talking to microservices. A single VPS from Linode or DigitalOcean at $5-10/month. 1GB of RAM with a swapfile if needed.

The backend? Written in Go, compiled into a single statically-linked binary on a laptop, SCP'd to the server, and run. No dependency hell, no virtual environments, no pip install nightmares. The deployment process is literally:

GOOS=linux go build -o app .
scp app root@yourserver:/opt/app/
ssh root@yourserver 'systemctl restart app'

A basic Go HTTP server handles tens of thousands of requests per second on potato hardware. No framework required.

SQLite Over Postgres​

This is the part that makes most developers flinch. SQLite — in production? For a real SaaS?

Yes. And here's why it works:

  • A local .db file communicating over the C-interface is orders of magnitude faster than making a TCP network hop to a remote Postgres server
  • Enable Write-Ahead Logging (WAL) with two pragmas, and readers don't block writers, writers don't block readers
  • On an NVMe drive, a single SQLite file handles thousands of concurrent users
PRAGMA journal_mode=WAL;
PRAGMA synchronous=NORMAL;

The enterprise mindset says you need an out-of-process database server. The lean mindset says: your database is a file on a disk, and that's a feature, not a bug. No connection pooling, no network latency, no separate server to manage and monitor.

Local AI Instead of API Bills​

This is where it gets really interesting. Hanov runs batch AI workloads — deep stock market research, summarizing thousands of quarterly reports — on a used RTX 3090 bought from Facebook Marketplace for $900. No OpenAI API bills. No rate limits. No "logic bug in my prompt loop that cost me $200 before I noticed."

The upgrade path is pragmatic:

  1. Start with Ollama — one command to spin up any model, perfect for iterating on prompts
  2. Move to vLLM for production — PagedAttention makes it dramatically faster for concurrent batch requests. Send 16 async requests and they all finish in roughly the time of one
  3. Transformer Lab for fine-tuning — when you need to customize models on local hardware

For frontier model tasks that can't run locally (user-facing chat, complex reasoning), he uses OpenRouter as a single API gateway to every major model. One integration, automatic fallback routing — if Anthropic goes down, it falls back to OpenAI. Users never see errors.

The Copilot Hack​

Here's a detail that resonates with any developer watching their AI tooling costs: Hanov uses a standard GitHub Copilot subscription (~$10-20/month) plugged into vanilla VS Code. Not Cursor. Not Windsurf. Not a $200/month API habit.

The trick: Copilot charges per request, not per token. So a brutally detailed prompt that tells the agent to "keep going until all errors are fixed" while it spends 30 minutes chewing through an entire codebase still costs roughly $0.04. Write good prompts with strict success criteria, hit enter, and let Microsoft subsidize your compute.

Why This Matters in 2026​

The timing of this playbook matters. Three trends are converging:

AI has collapsed the cost of building. A solo founder with good prompting skills and a $5 server can now build what took a 5-person team two years ago. The bottleneck isn't engineering capacity — it's finding the right problem.

VCs are asking harder questions about burn. The zero-interest-rate era of "growth at all costs" is over. Investors want to see capital efficiency. A founder who can demonstrate $10K MRR on $20/month infrastructure has a fundamentally different conversation than one burning $50K/month on AWS.

Simple stacks survive longer. Every abstraction layer you add is a maintenance burden. Every managed service is a potential single point of failure and a definite line item. A single server with a single binary and a single database file is boring — and that's exactly why it works.

The Real Lesson: Constraints Create Focus​

Hanov's stack isn't just about saving money. It's about what happens when you remove infrastructure as a variable:

  • You know exactly where your logs are — they're on the one server
  • You know exactly why something crashed — it's the one binary
  • You know exactly how to fix it — restart the one process
  • You have infinite runway — $20/month means you can iterate for years

The traditional startup playbook optimizes for scale that hasn't arrived yet. The lean playbook optimizes for survival and learning. When you're pre-product-market-fit, survival and learning are the only metrics that matter.

You can always migrate to Kubernetes later, when you actually have the traffic that justifies it. But you can't undo the months of infrastructure complexity you built "just in case."

When Lean Stops Working​

To be fair — this approach has limits. The $20/month stack works beautifully up to a point. When you need:

  • Multi-region redundancy for enterprise SLAs
  • Complex relational queries across millions of rows
  • Real-time collaboration features (CRDTs, WebSockets at scale)
  • SOC 2 compliance and audit trails

...you'll eventually need to graduate beyond a single VPS and SQLite. But that's a good problem to have, and by the time you have it, you'll have the revenue to solve it properly.

The mistake is pre-optimizing for scale you haven't earned yet.

Conclusion​

Steve Hanov's $20/month stack is a reminder that the tech industry's default complexity is a choice, not a requirement. You can build real businesses — profitable ones — on simple, boring infrastructure.

A single VPS. A Go binary. SQLite with WAL. Local AI for batch work. OpenRouter for frontier models. Copilot for coding.

Total cost: less than a Spotify subscription.

The question isn't whether this stack can scale to millions of users. The question is: do you need to scale to millions of users before you've found ten who love your product?

Start lean. Graduate when the data tells you to. And enjoy the infinite runway.


FAQ​

Q: Can SQLite really handle a production SaaS with thousands of users? A: Yes, with WAL mode enabled. SQLite with Write-Ahead Logging allows concurrent reads and writes without blocking. On NVMe storage, it handles thousands of concurrent connections. It's used in production by companies like Turso and Fly.io for their own infrastructure.

Q: What's wrong with using AWS for a new startup? A: Nothing is wrong with AWS — but it encourages over-engineering from day one. Managed services, EKS clusters, and RDS instances add up fast ($300+/month before your first user). A $5 VPS forces you to keep things simple and gives you the same runway as a $1M seed round with a high burn rate.

Q: How do you handle database backups with SQLite? A: SQLite backups are just file copies. You can use the .backup command for consistent snapshots, or simply copy the .db file during low-traffic periods. Combine with S3 or any object storage for offsite backups — still well under $20/month total.

Q: Is local AI really practical for production workloads? A: For batch processing — research, summarization, data extraction — absolutely. A used RTX 3090 ($900 one-time) running vLLM can process thousands of inference requests without per-token API costs. For real-time user-facing features, you'd still want a cloud API for latency reasons.


About the Author: Arkin is a software engineer and startup founder building Orbits Studio. He writes about lean engineering, indie hacking, and building products without the enterprise bloat. Find him at arkin-dev.com.

· 7 min read
Arkin Eliezer Julijanto

You're building a startup, watching every dollar like a hawk, and staring at cloud hosting bills that keep climbing. Your dev environment needs power, your staging server demands reliability, and production... well, production costs real money.

Meanwhile, that old laptop from 2019 sits in a drawer, gathering dust.

Here's the thing: thousands of bootstrapped founders are turning those forgotten laptops into collocated servers for a fraction of cloud costs. We're talking $5-15/month instead of $50-500/month for equivalent compute. You get full control, predictable pricing, and hardware that would otherwise be e-waste.

In this guide, I'll show you exactly how to repurpose old laptops as colo servers—from choosing hardware to finding facilities that accept laptops.