Contents
How to read this page: it is long on purpose, because the question it answers is large. Each section stands alone, so jump to the one you care about from the contents. Every number is measured, taken from a real bill, or labeled as an estimate. Last updated October 3, 2026.
If you read nothing else, read this.
Stackap is your own GitHub, Vercel and Supabase in one box. You rent a single server for the price of a lunch. You push your code to it with git push. Within about two minutes it has built the code in a container, checked that the new version is healthy, switched your domain over to it, and kept the old version one command away in case you change your mind.
Around that push it does everything else a small company needs a stack of subscriptions for. It hosts the git repositories. It issues and renews HTTPS certificates. It gives each app its own private Postgres database. It stores uploaded files. It runs scheduled jobs. It takes encrypted backups to a bucket you own, and it proves those backups restore. It watches itself and sends you a message when something is wrong.
Then, on top of that, it does one more thing the three-subscription stack cannot do for you at any price: it is multi-tenant. One Stackap can host many organizations, each walled off from the others, so the same box that runs your own products can run the products of your clients, your team, or your customers.
Stackap replaces a stack of hosted services with one server you own. It costs about eighteen dollars a month to run what used to cost its founder between five hundred and a thousand dollars a month. It already runs a real, public website with real data, and this page is being served by it right now.
The numbers, plainly
Every number on this page is either measured, taken from a bill, or clearly labeled as an estimate. We would rather lose your attention with an honest number than win it with a flattering one. Here are the ones that matter most:
- About $18 a month is the founder's all-in figure for what runs on Stackap today. The server itself is $8.49 a month.
- $500 to $700 a month is what the same founder was paying one hosted platform before. A larger multi-tenant product, still to be moved, was costing $700 to $1,000 a month across its hosting and database.
- About 96 seconds is how long the first real application, a 31,000-page Next.js website, took to build on the server.
- 24,988 database rows and 93 files were copied from the old stack to the new one with zero mismatches, checked table by table and file by file.
- 43 of 43 deliberate cross-tenant attacks were refused by the walls between organizations, and every one of eight deliberately broken walls was caught by the tests.
The honest part, up front
Stackap is young. It was built in two days, by one founder working with an AI coding assistant, and it has been running a public site for hours rather than years. It runs on one server, so if that server dies you are down until you restore from backup. Its backups are daily, so in a disaster you could lose up to a day of data. It has no content delivery network, no preview deployments and no built-in test runner. Section 12 lists every limit we know about, including the ones that are inconvenient to publish. If any of them is a dealbreaker for you, you should know that now, not on page forty.
If none of them is, keep reading. The rest of this page explains what Stackap is, why it exists, how it works, what is inside it, how it keeps tenants apart, how the first migration went, and exactly where the savings come from, with a calculator you can feed your own bill into.
One server that does the job of a whole stack.
Open the account page of any modern small software company and you will find the same three or four subscriptions. One service holds the code. A second builds that code and puts it on the internet. A third provides the database, the user accounts and the file storage. Usually a fourth sends the emails and a fifth watches for errors. Each is excellent at its job. Each has its own dashboard, its own login, its own pricing page, its own limits, and its own way of surprising you on the first of the month.
Stackap collapses that stack into a single program running on a single machine that you own. It is not a collection of scripts. It is one control plane, with one database, one API, one command-line tool and one dashboard, which manages everything your applications need in order to run.
What you actually do with it
The day-to-day experience is deliberately boring. You create a project. You get a git address. You push to it.
# once: create the project and point your repo at it
stackap create my-app --name "My App"
git remote add stackap git@your-box:my-app.git
# every time: this is the entire deploy
git push stackap main
# remote: build queued → image built → health check passed → live
# something wrong? one command puts the last version back
stackap rollback my-appThat is the interface. Everything else on this page is what happens behind it, and what you get for free because it happens in one place.
The parts, in one table
Here is how the hosted services you may be paying for map onto what Stackap does itself. The right-hand column is not a promise of feature parity with the giants; it is a statement of what exists and works today.
| Job | Usually a subscription to | In Stackap |
|---|---|---|
| Hold the code | A git host | Bare git repositories on the box, reached over a locked-down SSH user |
| Build and deploy | A deployment platform | Docker builds on the box, health-checked swap, one-command rollback |
| Domains and HTTPS | The same platform | Caddy with automatic Let's Encrypt certificates, routing that only switches on once DNS is correct |
| Database | A hosted Postgres | A private Postgres database and login role for every project |
| API over the database | The same hosted service | PostgREST, compatible with the Supabase JavaScript client |
| File storage | The same hosted service | The official Supabase storage service, writing to a Cloudflare R2 bucket you own |
| Scheduled jobs | A cron add-on | A built-in scheduler that can import a vercel.json as it stands |
| Backups | An add-on tier | Encrypted, snapshot-consistent, restored and verified on a schedule |
| Monitoring and alerts | An uptime service | Ten built-in checks and Telegram alerts, with reminders and recovery messages |
| Teams and clients | Seat licences, per-user pricing | Organizations, roles, per-organization git keys and project limits |
What it is not
Stackap is not a cloud. It does not have data centers, an edge network or an army of engineers on call. It is software that turns one ordinary server into a very capable application platform. The server comes from a hosting company; the bucket comes from Cloudflare; the intelligence is the part that is ours. That distinction matters, because it tells you exactly where the savings come from and exactly where the risks live. We will keep coming back to both.
The three-subscription stack is not expensive because the software is expensive. It is expensive because you are renting the same machines three times, plus a margin for the convenience of not thinking about it.
The stack tax.
There is a cost to modern web development that never appears as a line item. Call it the stack tax. It is what you pay, in money, time and attention, for the privilege of assembling an application platform out of other people's products. It has four parts, and most teams only count the first.
1. The money, which grows in the dark
Hosted platforms price by usage, and usage is the one thing a growing product cannot control. Build minutes, function invocations, bandwidth, database size, storage, seats, preview environments, log retention: each is a meter, each meter has a free tier, and each free tier ends at a different moment. A site that cost nothing in its first month can cost hundreds in its sixth without a single decision having been made. The bill is not high because anyone was careless. It is high because the pricing model is designed to track your success.
The founder of Stackap lived this directly. One hosted platform was costing between $500 and $700 a month for several websites. A second, larger product, a multi-tenant CRM with roughly a hundred customer domains, seventy-three scheduled jobs and a database of about four million rows, was costing between $700 and $1,000 a month across its hosting and its database. None of it was waste in the usual sense. The sites were live, the customers were served, and every line on the invoice corresponded to something that was actually being used. That is exactly the problem.
2. The glue, which is yours to maintain
Three platforms do not know about each other. Your code lives in one, your builds in another, your data in a third. The seams between them are your responsibility: webhooks that must be registered in the right place, environment variables copied between dashboards, secrets that exist in three vaults, a deploy that succeeded in one system and silently did nothing in another. When something breaks, the first hour is spent deciding which system is lying.
This is not hypothetical. During the work behind this page, one of the founder's deployments stopped following pushes five separate times, and the root cause on the fifth was almost comic: the continuous-integration service had exhausted its monthly budget, so checks never started, so the deploy platform waited forever for checks that were never going to report. Nothing was broken. Two services were each correctly doing their job, and the combination was an outage.
3. The lock-in, which you notice only when you leave
Every managed feature is also a hook. A proprietary database client, a platform-specific cron format, a storage API that exists in exactly one place: each saves a day of work and costs a week of migration later. Lock-in is not a conspiracy; it is simply what convenience looks like from the other side. The longer a product lives on a platform, the more of it is shaped like that platform, and the more expensive it becomes to be anything else.
4. The attention, which is the scarcest cost of all
The part that rarely makes it into a spreadsheet is the one that matters most to a small team: the number of places you have to look. Which dashboard has the error? Which one has the bill? Which login does this contractor need? How many tabs are open when a customer says the site is slow? A single place to look is not a luxury. It is the difference between a ten-minute fix and a lost afternoon.
The hosted platforms are good, and for many teams they are the right answer. If your bill is small, your traffic is global and spiky, and nobody on your team wants to think about servers, pay the bill and move on. Stackap is for a specific situation: you have several applications, the bills have become real money, you are comfortable owning a server, and you would rather own your stack than rent it. Section 13 draws that line carefully.
Because the arithmetic changed.
Nobody builds a platform for fun. Stackap exists because of a specific afternoon of arithmetic, followed by a specific realization about what has become cheap.
The arithmetic
The founder runs several businesses on software he writes himself: a classifieds site for New York City, a cleaning company's booking system, and a multi-tenant CRM that serves dozens of other businesses. Add up what those cost to host and the number was not small. Subtract what the underlying machines actually cost, about a cent an hour for a server that could run every one of them with room to spare, and the gap was enormous. That gap is not profit-taking or malice. It is the price of not having to think about servers. For a long time that was a fair price. The question was whether it still was.
The realization
The expensive part of running your own platform was never the server. It was the software around the server: the deploy pipeline, the certificate renewal, the database provisioning, the backups that you have actually tested, the monitoring that actually pages someone, the isolation between customers. Writing, testing and hardening all of that used to be a team's work for a year. It is the reason the hosted platforms exist, and the reason they could charge what they charge.
AI coding assistants changed the cost of that work. Not to zero, and not without judgment: every wall in Stackap was designed by a human who knew what he wanted, and every claim in it is backed by a test that was written to fail if the claim were false. But the typing, the research, the cross-checking against documentation, the writing of over two hundred and fifty tests, that part now takes days instead of quarters. Stackap, from first design document to a public website running on it, took two days.
When the cost of building the platform falls by an order of magnitude, the economics of renting it have to be re-examined. Most people have not re-examined them yet.
The constraints we gave ourselves
A platform built in two days could easily be a toy. These are the rules that kept it from being one:
- Nothing is "done" until a check that could have failed has passed. The founder's standing rule for this work was blunt: verify everything, or say nothing. Every feature described on this page was exercised against a real system, not just compiled.
- Never touch production without a yes. The first application was copied onto Stackap as a staging site while the live one kept serving. The switch was one DNS edit, approved by a human, at a moment he chose.
- Prefer proven software to clever software. Postgres, Caddy, Docker, PostgREST, the official Supabase storage service, Cloudflare R2. Stackap's own code is the glue and the guard rails, not a reinvention of the engine.
- Make failure visible. A scheduled job that never ran says so. A backup that was never restored is never called verified. A deploy that fails its health check never goes live.
- Copy walls that already work. The tenant isolation is modeled on the system that already keeps a hundred customers' data apart in the founder's CRM, down to the style of test that attacks it.
The goal
The immediate goal is modest and concrete: move every product the founder owns onto one box he controls, and stop paying the stack tax. The larger goal is the reason the multi-tenant work exists. If one box can host his products, it can host a few other people's products too. A small agency, a studio with a dozen client sites, a team of freelancers sharing infrastructure: any group that currently pays a hosted platform per seat and per project is a candidate. That is a second, separate use for the same software, and it is why the walls between organizations are built the way they are.
From git push to live, step by step.
The most useful way to understand Stackap is to follow one push all the way through. Nothing in this section is simplified for effect; it is the actual sequence, in the actual order.
Step 1: the push
Your laptop talks to a dedicated, deliberately restricted user on the box over SSH. That user cannot open a shell, cannot run arbitrary commands, and cannot see anything except git repositories. The forced command behind it accepts exactly two operations, sending and receiving a repository, and rejects everything else. A repository name that is not allowed looks exactly like one that does not exist, so a key can learn nothing about what it is not permitted to touch.
Step 2: the hook
When the push lands, a hook inside the repository tells the control plane over a localhost-only, secret-protected endpoint. The control plane records the push and queues a build. Only pushes to the project's production branch queue a build; other branches are stored and ignored.
Step 3: the build
The build runs inside Docker on the same machine. If your repository contains a Dockerfile, Stackap uses it. If it does not and the project is a Next.js application, Stackap generates one. The build is careful about secrets: public build-time values are passed through, everything else is replaced with harmless placeholders, and the final image starts from a clean base so no build-time scaffolding leaks into what runs in production. Real secrets exist only at runtime.
Step 4: the health check
The new container starts alongside the old one, not instead of it. Stackap polls it until it answers successfully or until a timeout expires. A container that crashes on start, hangs, or returns an error is marked unhealthy and discarded. At no point during this has a visitor been sent to it.
Step 5: the swap
Only after the health check passes does Stackap change the routing table, inside a database transaction, so that the change either happens completely or not at all. Caddy begins sending traffic to the new container. The previous version is kept running as a rollback target. If anything in the swap fails, including the call to the proxy, routing is left exactly as it was.
Step 6: rollback, if you want it
One command re-activates the previous deployment, health-checking it first. Rollback is not a special mode with special risks; it is the same swap, pointed backwards.
The deploy path was exercised with a deliberately broken release. The broken build never went live, the previous version kept serving, and the failure was recorded where you can see it. A system that only works when everything works is not a platform; it is a demo.
Domains and HTTPS
You attach a domain to a project and Stackap tells you the one DNS record to create. Routing for that domain stays off until the record is correct, and certificates are obtained automatically only after that. The reason is practical: a certificate request against a domain that does not point at the server yet fails noisily and can trip rate limits. Making DNS the gate removes a whole class of confusing half-working states.
One real-world detail is worth sharing, because it is the kind of thing that only appears when you do this for real. When the first production domain was switched over, its DNS record had a time-to-live of twenty-four hours. Some visitors kept reaching the old host for hours after the change. The lesson is old and unglamorous: lower the TTL a day before any cutover. It is now in the migration checklist.
Every part, and what it really does.
This is the feature tour. For each piece, we say what it does and, where it matters, how we know it works. If a capability is thin, we say that too.
- Git hosting
- Every project gets a bare git repository on the box and a git address to push to. Access is over SSH through a single restricted user whose forced command allows only sending and receiving repositories. Repository names are validated strictly, and every organization's keys are limited to that organization's repositories.
- Build
- Docker builds on the box, using your Dockerfile or a generated one for Next.js. Build-time secrets never reach the running image. A typical large Next.js build, the 31,000-page classifieds site, took about 96 seconds and produced a 164 MB image.
- Deploy and rollback
- A new version starts beside the old one, must pass a health check, and only then receives traffic through a transactional routing swap. One live deployment per project; the previous one is retained, and one command restores it.
- Domains and HTTPS
- Caddy terminates TLS with automatic certificates. Routing for a custom domain stays off until its DNS points at the box, and the certificate is requested only after that.
- Environment variables
- Encrypted at rest with AES-256-GCM under a master key, bound to the project and the variable name so a value cannot be swapped between them. Never shown back in plain text; the dashboard and CLI display masks. Injected only when a container starts.
- Databases
- Each project can have its own Postgres database and its own login role. The role can connect to its own database and no other; connection rights on the system databases are revoked. This was tested by attempting cross-database connections with two real roles. The connection string is stored encrypted and injected at runtime.
- Data API
- PostgREST sits in front of a project's database, so an application written for the Supabase JavaScript client can keep working unchanged. It was tested with the real client against the query shapes a large production codebase uses: filters, joins, upserts, counts, and database functions. Row-level security policies are honored, and the row cap matches Supabase's default of 1,000.
- File storage
- The official Supabase storage service, writing objects to a Cloudflare R2 bucket you own. Uploads, public URLs, listing, deletion and signed upload URLs all work with the standard client. The storage metadata lives in the project's own database, so a database backup also captures it.
- Scheduled jobs
- A built-in scheduler on UTC time. It runs each job once per fire time, never lets runs of the same job overlap, and records a visible "missed" run if the scheduler itself was down. A
vercel.jsoncron block can be imported as it stands. Jobs call your own application on localhost with a bearer secret, so a job cannot be pointed at an outside address. - Logs
- Build logs and a live runtime tail from the running container, from the CLI or the dashboard.
- Dashboard and CLI
- A static dashboard served under a strict content-security policy, and a command-line tool covering login, projects, deploy, rollback, logs, environment variables, domains, crons and status.
- Migrator
- A tool that copies a Supabase project's schema and data into a Stackap project. It is read-only against the source by construction: it refuses to send anything other than a SELECT. It then verifies row counts table by table.
Backups, in detail
Backups are where hosted platforms most often over-promise and where self-hosting most often under-delivers, so this part is built with extra care.
- Consistent. The dump is taken from a single exported database snapshot, and the table row counts are recorded from the same snapshot, so the manifest describes the dump exactly, even while the application is writing.
- Encrypted. Every backup is encrypted with AES-256-GCM before it leaves the server. The key is derived from the master key, and the object's name is authenticated into the ciphertext, so a backup cannot be renamed or swapped without detection.
- Off the box. Backups go to a Cloudflare R2 bucket. If the server vanishes, the backups do not.
- Restore-tested. A restore only ever goes into a brand-new database, never over a live one. Verification restores the latest backup into a temporary database, compares every table's row count with the manifest, and only an exact match marks the backup verified. The temporary database is always dropped.
- On a schedule. The loop checks hourly: a backup for any database without a good one in the last day, a verification weekly, and pruning daily, always keeping the newest three backups.
- Code too. Every git repository, including Stackap's own source, is bundled, encrypted and uploaded the same way, and restore-verified weekly.
Monitoring, in detail
Ten checks run continuously: CPU load, memory, disk, Postgres, running containers, database backups, repository backups, certificates, deployments, and scheduled jobs. Alerts fire on transitions only. You get one message when something starts failing, a reminder every six hours while it stays broken, and a recovery message when it clears, delivered to Telegram and written to the service log. The point is signal: an alert system that cries wolf is an alert system that gets muted.
While this page was being written, a monitoring alert flagged three scheduled jobs as failed. They had not failed. The scheduler had recorded "missed" runs for fire times that predated the jobs' existence, because a freshly imported job looked, to the scheduler, like one that had been neglected. The fix was a rule that a job with no history cannot have missed anything, a test that fails without it, and a deploy. The alert system did its job by being annoying about a real bug.
One box, many organizations, solid walls.
A platform that hosts only its owner's projects is a tool. A platform that can safely host several independent parties is a business. Stackap is built to be the second, and the difference lives entirely in one question: if two organizations share this machine, how sure are you that neither can see or touch the other?
The model
Every project, access token and git key belongs to exactly one organization. The operator's own work lives in a special platform organization. Everyone else gets their own, created by the operator, with an owner token that is shown once. Three roles exist:
- Platform admin
- The operator. Creates and disables organizations, sees host-wide health and alerts. Exists only in the platform organization.
- Owner
- Runs an organization: creates projects, manages tokens and git keys, and works on everything inside the organization.
- Member
- Works on the organization's projects. Cannot mint or revoke tokens or manage keys.
The same walls that already work
The founder's CRM serves roughly a hundred separate businesses from one codebase and one database, and its tenant isolation has been hardened through security audits and a growing suite of attack tests. Stackap copies that approach rather than inventing a new one, layer for layer:
- A single wall module. Every lookup of a project, and every lookup of anything reached by an identifier, such as a build, a backup, a token or a key, goes through one module that filters on the caller's organization. The organization comes from the access token and from nowhere else. A different organization in a request body, a header or a query string changes nothing.
- Uniform not-found. A resource in another organization and a resource that does not exist produce byte-for-byte identical responses. An attacker cannot even learn that a project name is taken by someone else's project.
- A static audit that fails the build. A test reads every route's source and fails if any query touches projects, tokens, keys, builds or backups without an organization filter. The audit logic is itself tested with deliberately leaky examples, including the subtle one where a query merely selects the organization column without filtering on it. A short, reasoned allow-list covers the one internal endpoint that is not tenant-facing, and a test fails if an allow-list entry goes stale.
- An attack suite. Forty-three tests create two real organizations and then try to cross the wall on every route, which we describe below.
- Database-level locks. Two triggers hold even if application code is wrong: a project can never be moved to another organization, and an administrator token can exist only in the platform organization. Exactly one platform organization is allowed to exist.
- A git wall. Each organization's SSH keys are written into the server's key file with an explicit list of that organization's repositories. A repository outside the list is indistinguishable from one that does not exist.
What the attack suite actually attempts
- Reading every project route, eleven in all, with another organization's project name, and comparing the answer to a project name that does not exist. They must match exactly.
- Writing to the other organization's project through every writing route: environment variables, scheduled jobs, domains, backups, restores, rollbacks, database provisioning. Each must fail, and the victim's data must be unchanged afterward.
- Looking up another organization's build, build logs, backups, tokens and keys by identifier.
- Restoring another organization's backup through the attacker's own project, and restoring a backup from a different project in the same organization through the wrong project.
- Smuggling another organization's identifier in a request body, a header and a query string, and checking that the record ends up owned by the caller regardless.
- Squatting another organization's project name, and claiming a domain name another organization already attached.
- Escalating: a member minting tokens, an owner minting an administrator token, tenant tokens reaching organization administration, host status or alerts.
- Operating on a disabled organization, whose tokens must stop working instantly, and exceeding a project limit.
Passing a test suite proves little if the tests cannot fail, so the walls were broken on purpose. Eight different protections were removed one at a time, and the suite caught every one of them. Finally, the same attacks were run against the real, deployed API using two throwaway organizations, which were then deleted. The result was the same: not found, forbidden, or unchanged.
These walls keep one organization's data and controls away from another's. They do not sandbox the code an organization deploys. That code runs in containers on the same machine, and containers are not a security boundary against a determined attacker. Until builds are sandboxed, creating organizations is an operator action, meant for people you trust. Postgres row-level security as a second lock under the application wall is the next planned layer.
What is locked, and how.
A security section should be a list of specific controls, not a mood. These are the ones that exist today.
| Area | Control |
|---|---|
| Network | Only SSH, HTTP and HTTPS are open to the internet. Postgres listens on localhost and the internal container network only; its port is closed to the outside. A firewall and an intrusion-banning service run on the host. |
| Secrets at rest | Environment variables and database connection strings are encrypted with AES-256-GCM under a master key and bound to their project and name. Access tokens are stored only as SHA-256 hashes, so a database leak does not reveal usable tokens. |
| Secrets in motion | Secrets are passed to containers through a private, mode-0600 environment file, never on the command line where any process listing could read them. |
| Git access | A restricted SSH user with a forced command. No shell, no port forwarding, no arbitrary commands. Per-organization repository allow-lists. |
| Internal endpoints | The push hook accepts only localhost connections and requires a shared secret compared in constant time. |
| Containers | No new privileges, CPU, memory and process-count limits on every container. Generated images run as an unprivileged user. |
| Databases | One role per project, no superuser rights, no ability to create roles or databases, connection rights limited to its own database. |
| Backups | Encrypted before upload, authenticated against tampering, restore-only-into-new-databases. |
| Dashboard | Static files under a strict content-security policy, rendering data only as text, never as markup. |
| Audit | Pushes, deploys, rollbacks, token and key changes, backups, restores and organization actions are recorded with who did them. |
What we do not claim
We have not had an independent penetration test. We hold no compliance certifications. The platform is two days old. What we can say is that each control above has a test that tries to defeat it, and that the design deliberately favors boring, proven components over novel ones. If your application handles regulated data, you should treat Stackap the way you would treat any new infrastructure: review it, test it, and decide with your own eyes.
The first move: a real site, real data, real visitors.
Claims are cheap. The first application moved onto Stackap was The NYC Classifieds, a pre-launch Next.js website that verifies every member with a selfie and a location check at their New York address. It has about 31,600 pages in its sitemap, a Postgres database of 43 tables, user-uploaded images, email-based sign-in, and an advertiser. It was hosted on a deployment platform and a hosted database, and it was moved to Stackap in roughly a day of work. Here is how it went, including the parts that did not go to plan.
Staging first, production untouched
The site was copied onto Stackap as a staging site on its own address while the live site kept serving. The staging build took about 96 seconds on the server. The environment was deliberately inert: messaging and payment switches were off and provider keys were dummies, so a staging site could not email, text or charge anyone.
The data
The migrator copied the live database's public schema and data using SELECT statements only. It found something the repository's migration files did not mention: six tables existed only in the live database, created by hand at some point. The migrator rebuilt them from the live catalog. The lesson is one every migration teaches again: the running database, not the code repository, is the truth about what exists. The first copy was 24,972 rows. The final copy, taken shortly before the switch, was 24,988 rows across 43 tables with zero mismatches between source and target.
The files
The site stores 93 uploaded files, about 57 MB, in two storage buckets. They were downloaded, uploaded to Stackap's storage, then read back through the storage API and compared by SHA-256 checksum against the originals: 93 of 93 matched. Sixty image addresses stored in forty-two database rows were rewritten to the new storage location, and a scan of every text, JSON and array column in the database found none left pointing at the old host.
Comparing the two sites
Rather than eyeball it, the two sites were fetched page by page and compared after normalizing the host name and deployment hashes. First pass: every status code matched, but a few hundred bytes of CSS differed on every page. The cause was that the staging copy had been built from a local branch that was five commits behind what the live site was actually running. The comparison caught what no one had noticed. After rebuilding from the right commit, twenty-six key pages, sixty-four randomly sampled data pages and the CSS bundle itself matched exactly, and later a full pass of 87 pages did too. Screenshots of the home page, the neighborhood board and the sign-up page, taken from both sites, were visually identical.
The part nobody can skip: a real sign-up
Pages rendering is not the same as the product working. On the new server, using the real domain, a complete sign-up was run: request an email code, receive it, verify it, create an account with an address and a selfie, store the selfie, log in with a PIN, get refused with a wrong PIN, read the session, upload a photo. The verification email genuinely arrived, from the site's own address, with the right code inside. The test account and files were then deleted, and a count confirmed none remained.
The switch, and the mistake
The cutover was one DNS change, made by the owner. It was not perfect. The edit added a second address record rather than replacing the first, so for a few minutes visitors alternated between the old and new hosts, and those who landed on the new one hit a server not yet ready for the domain. It was spotted within minutes, corrected, and every page verified afterward. The existing records also had a twenty-four-hour cache lifetime, so some visitors continued to reach the old host for hours. We mention it because pretending a migration is flawless is how people get hurt by the next one. The old host and database were left running as a fallback for a week, and the old host's scheduled jobs were switched off the same hour so that nothing ran twice.
| What was checked | Result |
|---|---|
| Database rows, source versus target | 24,988 / 24,988, 0 mismatches |
| Files, checksum against the original | 93 / 93 |
| Pages identical to the live site | 87 / 87 |
| Old-host image references remaining | 0 |
| End-to-end sign-up, including email | Passed; test data removed |
| Cross-organization attacks refused | 43 / 43, plus a live run on the deployed API |
How to move your own application
The sequence that worked is general. It is also the checklist the migrator and the comparison tools were built around, so you can follow it for an application of your own.
- Inventory. List the environment variables, scheduled jobs, webhooks, domains and storage buckets the application depends on. The code tells you what it reads; the running platform tells you what is actually set. They are rarely identical.
- Lower the DNS cache lifetime on the domain to five minutes, a full day before the switch.
- Stand up a staging copy on Stackap with messaging and payments switched off.
- Copy the data with the read-only migrator, and verify counts table by table.
- Copy the files, verify them by checksum, and rewrite stored addresses. Then scan every column for leftovers.
- Compare page by page against the live site, normalizing host names, until the differences are explained or gone.
- Run the real flows end to end, on the real domain, pinned to the new server before DNS moves.
- Switch, then verify, then silence the old side. Change the single record, check every flow again, and turn off the old platform's scheduled jobs the same hour. Keep the old stack running for a week as a fallback.
Where the money goes, and where it stays.
This is the section most people scroll to first, so we will be exact about what is measured, what is reported, and what is an estimate.
The founder's own numbers
| What | Before | On Stackap | Status |
|---|---|---|---|
| Hosted platform for several sites | $500 to $700 / month | about $18 / month, all in | Reported by the founder; the server alone is $8.49 |
| Multi-tenant CRM (about 100 customer domains, 73 scheduled jobs, about 4M database rows) | $700 to $1,000 / month | $20 to $65 / month | Estimate, not yet moved or measured |
| Retired self-hosted server, idle | about $120 / month | $0 if deleted | Decision pending |
Do not add the first two rows together. The larger product's bill overlaps with the first, because they were hosted on the same kind of platform. Treat them as two separate scenarios, not a running total.
The arithmetic, shown
- Monthly saving on the hosted platform: $500 minus $18 is $482, to $700 minus $18, which is $682. That is 96% to 97% less.
- Yearly: $482 times 12 is $5,784, up to $682 times 12, which is $8,184.
- Over three years: $17,352 to $24,552.
- For the larger CRM, using the estimate, the monthly saving would be between $635 (high end of the new cost against the low end of the old) and $980 (the reverse). That would be 91% to 98% less. Until it is moved and measured, treat that as a forecast.
Why the gap is so large
A hosting company's server costs a cent an hour or so. A hosted platform sells you that capacity as thousands of fine-grained meters, each priced with a healthy margin, plus the convenience of not managing anything. On Stackap you pay for the capacity directly. The savings are not a trick. They are the margin on the convenience, which is exactly what you give up in exchange for owning the thing.
What is not in the number
The honest counterweight is your time. Running your own platform means someone applies updates, watches the alerts and decides what to do in an incident. Stackap automates the routine parts, but it does not abolish them. A useful way to think about it: at a saving of about $580 a month, Stackap pays for itself unless it costs you more than roughly six extra hours a month at a hundred dollars an hour. For a team with several apps and a person comfortable with a terminal, that is a low bar. For a team with one small site on a free tier, the savings are small and the case is weak. The calculator below lets you test your own situation.
Try your own numbers
Estimated saving shown above.
This is an estimate, not a quote. It counts servers and extras, not your time, and the larger server prices are estimates, not purchases we have made.
Three illustrative shapes
These are not customers and not measurements. They are arithmetic on assumptions, to show how the saving scales with the size of the bill.
| Shape | Assumed bill | Stackap | Monthly saving |
|---|---|---|---|
| A freelancer hosting ten small client sites | $150 | $8.49 + $5 = $13.49 | about $137 |
| A startup with three apps and a database each | $400 | $20 + $8 = $28 | about $372 |
| An agency with forty client sites | $1,200 | 2 × $20 + $15 = $55 | about $1,145 |
The pattern is the point: the cost of Stackap grows with the number of machines, which grows slowly, while a metered bill grows with every site and every user. The larger your bill, the more of it is margin you can keep.
What you get besides a smaller bill.
Cost is the headline, but it is not the only reason to own your stack. These are the benefits we have actually felt while building and using it.
- One place to look
- Code, builds, logs, databases, files, schedules, backups and alerts live behind one API, one command-line tool and one dashboard. When a customer says the site is slow, there is one place to start.
- A deploy is a push
- No pipeline files, no queue to wait in, no separate budget that can run out and silently stop your deploys. On a hosted setup we watched deploys silently stop following pushes five times, the last because a continuous-integration budget ran out.
- Predictable cost
- A server has a price, not a meter. A traffic spike makes the machine busier, not the invoice larger. You can read your own future bill off a pricing page for a server.
- No lock-in
- Postgres, Docker, git, Caddy, and files in a bucket you own. Your data sits in a database you can dump with standard tools, your backups are in your own account, and the Supabase-compatible layer means your application code does not change on the way in or on the way out.
- Compatibility, not conversion
- Applications written for the Supabase client keep working,
vercel.jsonschedules import as they are, and a Next.js project builds with no Dockerfile. The move is mostly configuration, not rewriting. - Backups you have actually restored
- Verified restores on a schedule, row counts compared, failures alerted. It is a standard people claim and few meet.
- Control of where data lives
- You choose the server's country. Today's box is in Germany, and a United States server is a matter of choosing a different machine, not a different product.
- Isolation you can sell
- Because organizations are walled apart, one box can serve clients, teammates or customers. Hosting becomes a service you can offer, not only a cost you bear.
- Honest failure
- Failures are visible by design: unhealthy deploys never go live, missed jobs are recorded, unverified backups are not called verified, and a noisy alert gets investigated rather than muted.
- Built to be driven by scripts and agents
- Everything the dashboard does is an authenticated API call. That makes the platform easy to automate, and easy for a coding assistant to operate on your behalf.
Side by side, fairly
Benefits only mean something next to the costs, so here is the comparison with the three-subscription stack, including the rows where it wins.
| Question | Three hosted subscriptions | Stackap |
|---|---|---|
| Shape of the bill | Metered: usage, seats, add-ons | Flat: the price of a server |
| Places to look | Three or more dashboards | One |
| Where the data lives | The vendor's cloud | Your server and your bucket |
| Leaving | Possible, with migration work | Standard parts; designed for it |
| Global traffic and scale | Strong: edge networks, automatic scaling | Weak today: one server, no edge |
| Who carries the pager | The vendor | You, helped by alerts |
| Preview deployments, CI | Built in | Not yet |
| Compliance certifications | Often available | None |
| Hosting for clients or teammates | Per-seat and per-project pricing | Organizations, roles and limits built in |
| Time to first deploy on a new project | Minutes | Minutes, once the box exists |
Read the middle rows honestly. If you need global scale, certifications and someone else holding the pager, the hosted platforms are the better product, and you should keep using them. Stackap wins where the bill, the ownership and the single place to look matter most.
What Stackap is not good at yet.
A platform page that lists no weaknesses is a page that has not been read carefully, or has been read by someone who wants to sell you something. This is the list we would want to be given. Each item is real today.
- One server
- Everything runs on one machine. If it fails, you are down until you restore from backup onto a new one. The full restore-from-scratch drill on a fresh machine has not been run yet; it is the next test we intend to perform, and until it is done you should treat the recovery time as unproven.
- Daily backups
- Databases are backed up once a day. In a disaster you could lose up to a day of data. There is no point-in-time recovery yet, which hosted databases offer.
- The control plane's own database
- The database that records every project's configuration, encrypted secrets and tokens is not yet in the automated off-site backups. A manual copy exists; automating it is on the near-term list, and it is the most important gap on this page.
- No edge network
- There is no global content delivery network in front of the box. Visitors far from the server see more latency than they would on a platform with points of presence worldwide. The current server is in Germany. A server in the United States, or a CDN in front of the site, would improve that.
- No previews, no CI
- Branch preview deployments and a built-in test runner do not exist. Whatever you push to the production branch goes live if it builds and passes the health check. Run your tests before you push.
- Tenant code is not sandboxed
- Organizations are walled apart at the data and control level, but the code each organization deploys runs on the same machine, not inside a hardened sandbox. Until that changes, organizations are created by the operator for parties that are trusted.
- Second lock not built
- Postgres row-level security as a database-level backstop under the application's tenant wall is planned, not built. Today the guarantee rests on the wall module, the static audit, the database triggers and the attack tests.
- No organization screen
- Organizations are managed through the API and command line. The dashboard does not have screens for them yet.
- Unproven at scale
- The first application is a 25,000-row database. The larger multi-tenant CRM, with about four million rows, a hundred domains and seventy-three scheduled jobs, has not moved yet, and its inventory will surface things the first move did not.
- A test bug, found and fixed
- For a day, nine tests in the data-API compatibility suite failed. The cause was a bug in the test itself, which passed a database password with stray quote characters, not in the platform; the live site had been verified separately against the real system throughout. The suite now passes, ten of ten. We mention it because it was open while this page was being written, and an honest limits list should include the loose ends too.
- Young
- Two days of building and hours of production life. No independent security review, no compliance certifications, a bus factor of one founder plus an AI assistant. These are normal for software this new, and they are exactly why section 13 is about who should wait.
A good fit, and a bad one.
It is probably for you if
- You run several applications, and your hosting, database and storage bills have become real money.
- Someone on your team is comfortable with a terminal and a server, or you work with a coding assistant that is.
- Your applications are standard: Next.js or any container, Postgres, files, some scheduled jobs.
- You value owning the stack and being able to leave, more than you value a vendor that carries the pager.
- You host sites or tools for clients and would like to do it from one controlled place, for people you trust.
It is probably not for you, yet, if
- You have one small site on a free tier. The savings are tiny and the effort is not.
- Your traffic is global and bursty and needs an edge network and automatic scaling to many machines.
- You handle data under strict compliance requirements that demand certified infrastructure and independent audits.
- You need preview environments for every pull request and a managed test pipeline as part of deploys.
- Nobody on your team wants to be responsible for a server, even a well-instrumented one.
If a bad hour of downtime would be an inconvenience, Stackap is a reasonable bet today. If a bad hour would be a crisis, wait for the restore drill, point-in-time recovery and a second server.
The honest roadmap.
This is what is planned, in rough priority order. It is a statement of direction, not a promise of dates.
- Restore drill on a fresh machine. Prove that, with the server gone, everything comes back from the bucket and a copy of the master key.
- Automated off-site backups of the control plane's own database, verified the same way as the others.
- Move the larger multi-tenant CRM, which is the real scale test and the largest saving.
- Point-in-time recovery for databases, to shrink the worst-case data loss from a day to minutes.
- Row-level security as a second database-level lock beneath the tenant wall.
- Sandboxed builds and runtime, which is the step that would make it reasonable to open organization creation beyond trusted parties.
- Organization screens in the dashboard, and a standby server for fast failover.
- Preview deployments and an optional test gate before a push goes live.
Questions people ask.
What happens if the server dies?
Your sites go down until you restore. Databases are backed up daily to a bucket in a different company's cloud, encrypted, and restore-tested; repositories are backed up the same way. The honest caveat is that the full drill of rebuilding everything on a fresh machine is still on the to-do list, so the recovery time is unproven. A standby server is on the roadmap.
Can I leave if I do not like it?
Yes, and that is a design goal. Your data is in standard Postgres that you can dump with ordinary tools. Your files are in your own bucket. Your applications are containers and plain git repositories. The Supabase-compatible layer means application code does not need to change on the way out any more than it did on the way in.
Does it only work with Next.js?
No. Any application that can run in a Docker container works: give it a Dockerfile that listens on the port Stackap provides. Next.js is special only in that Stackap will generate the Dockerfile for you if you do not have one. This very page is a plain static site served by a small web server in a container.
How compatible is it with Supabase?
For the parts we use, very. The data API is PostgREST, the same engine Supabase uses, and file storage is the official Supabase storage service. An application using the standard JavaScript client was tested against the kinds of queries a large production codebase makes. What it does not include is Supabase's authentication service, realtime subscriptions or edge functions; applications that depend on those would need work.
Why a server in Germany?
Because it was inexpensive and available at the time of the first build. It is not a design constraint. Visitors in North America see a little extra latency, and a United States server costs more. Moving is a matter of provisioning another machine and restoring from backup.
How long does a deploy take?
For the large Next.js site, the build was about 96 seconds, and the whole path from push to live was a couple of minutes. A static site like this one builds in a few seconds.
Do I need to be a DevOps engineer?
You need to be comfortable with a terminal, SSH and DNS records. You do not need to hand-configure certificates, proxies, container networking or backup scripts, because those are the parts Stackap does. If you can follow a hosting provider's setup guide, you can run it. If you would rather not, the platform is also designed to be driven by an AI coding assistant.
How are my secrets protected?
Environment variables and database connection strings are encrypted at rest and bound to their project and name. They are never shown back in plain text and are handed to containers through a private file rather than the command line. Access tokens are stored only as one-way hashes. The master key that unlocks everything lives outside the server's own database; if it is lost, encrypted variables and backups cannot be recovered, so keep a copy in a password manager.
Can I use my own domain, including the bare one?
Yes. Attach the domain to a project, create the single DNS record Stackap shows you, and routing and the certificate switch on by themselves once DNS is correct. Lower the record's cache lifetime a day before any production switch. This site's bare domain redirects to the www address.
What does it really cost to run?
The server we run is $8.49 a month. The founder's reported all-in figure for what runs on it today is about $18 a month, including the storage bucket and incidentals. A larger server for a bigger product is estimated at $20 to $65 a month. Section 10 has the arithmetic and a calculator.
Is it open source? Can I get it?
Stackap is the founder's own software and is not publicly distributed yet. Access is by invitation while the remaining gaps in section 12 are closed. If you are interested, the last section of this page says how to ask.
How is it different from other self-hosted deployment tools?
Tools such as Coolify and Dokploy cover deploying applications and databases on your own server, and they are worth a look. Stackap's particular combination is the part that surrounds the deploy: Supabase-compatible data and storage layers, verified encrypted backups with restore testing, a built-in scheduler that imports vercel.json, and walled multi-tenant organizations. We have not benchmarked against them and do not claim to be better at what they do.
Is it production-ready?
It is running a real public website today, and it passed the checks described in section 9. It is also two days old, on one server, with the limits listed in section 12. Whether that is ready depends on what a bad hour of downtime would cost you.
Can an AI agent operate it?
Yes, and it is how it was built. Everything the dashboard can do is an authenticated API call, the command-line tool wraps the same API, and output is plain text. That makes it straightforward for scripts and coding assistants to deploy, read logs, change variables and roll back.
Terms, in plain English.
- Control plane
- The part of Stackap that manages everything else: its API, its database of projects and settings, and its background workers.
- Project
- One application, with its repository, domains, variables, database, schedules and backups.
- Organization
- A group that owns projects, tokens and git keys, walled apart from every other organization.
- Tenant
- One organization, seen from the point of view of a platform that serves several of them.
- Health check
- A request Stackap makes to a new version before it receives visitors. It must answer successfully or the deploy is abandoned.
- Rollback
- Re-activating the previous version of a project, health-checked first.
- TTL
- Time to live: how long other computers may remember a DNS answer. A long one slows down any change of server.
- PostgREST
- Software that turns a Postgres database into a web API, used by Supabase and by Stackap.
- R2
- Cloudflare's object storage, which Stackap uses for backups and uploaded files. It follows the S3 interface and does not charge for data leaving it.
- Row-level security
- A Postgres feature that restricts which rows a database user may read or change, enforced by the database itself.
- Point-in-time recovery
- Restoring a database to any chosen moment, not only to the last nightly backup. Planned, not built.
- Master key
- The one secret from which Stackap's encryption keys derive. Lose it and every encrypted variable and backup is unrecoverable.
Ask to be let in.
Stackap is invite-only while the gaps in section 12 are closed, starting with the restore drill and the backup of the control plane's own database. If you run several applications, your hosting bills have become real money, and you would like to see whether a platform like this fits, tell us what you run and what you pay. We will answer with an honest view of whether Stackap would help or whether you should stay where you are.
Include roughly how many applications you run, which services you use today and your approximate monthly bill. We will never share it.