Elements vs Render
Render is a cloud hosting platform that builds and runs apps from a Git repository. You connect a repository, and on every push Render runs your build command, an optional pre-deploy command and your start command, then moves traffic to the new instance (deploys). It hosts web services, static sites, private services, background workers, cron jobs and workflows, and it offers managed Render Postgres and Key Value, a Redis-compatible store. A Blueprint file describes a set of services in YAML (docs). Its revenue is hosting: a monthly workspace plan, a charge for each running instance, and bandwidth and build pipeline minutes beyond the plan's allowance (pricing).
Elements is not a hosting company. It is one coherent system for writing, testing and shipping the app, and the pieces Render bills as services are features inside it: background jobs and cron come with the default framework, and Postgres comes bundled. Deploys go over SSH to an Ubuntu server from the provider of your choice. Elements itself costs a set amount per machine each month, and it counts no minutes, instances or requests (pricing).
The difference is what each company charges for. Render sells the servers your app runs on, and every worker, cron job and database is another service on the bill. Elements sells the tooling that builds, tests and deploys your app, and the app, its jobs, its cron schedule and its Postgres all share one server, billed by its provider at that provider's listed rate.
At a Glance
| Elements | Render | |
|---|---|---|
| What it is | One coherent system that builds, tests and deploys the app | A host that bills per service |
| What you pay for | Tooling, per machine, per month (pricing) | A workspace plan, each service's instance, and usage past the plan's allowance (pricing) |
| Where your app runs | One server of yours, from DigitalOcean, Hetzner, AWS or elsewhere | Render's infrastructure |
| A deploy | Changed files only, usually under a second, into the running server | A build in Render's build pipeline, then a new instance built and booted |
| Tests and migrations | Part of the deploy: test database migrated, tests run on each machine, app database migrated last | Whatever you put in a pre-deploy command, run against your real database; no built-in test step |
| Background jobs and cron | Code in the app, deployed with it, queued in the app's Postgres | A worker service and a cron job service, each with its own charge |
| Database | Bundled Postgres, or any Postgres host | Render Postgres, a separate service |
| Moving away | Change a server address and deploy | Recreate each service, its environment and its Blueprint on another host, and move Render Postgres out |
Every Part of a Render App Is a Separate Service on the Bill
Render prices each service by its instance type, so the bill is the sum of the services your app is made of. An app with background work is a web service, a background worker, a Render Postgres database, often a Key Value instance for the worker's queue, and a cron job or two. A background worker is its own continuously running service that usually polls a task queue, such as one backed by Key Value (background workers). Each cron job is its own service, with a minimum monthly charge (cron jobs). Build pipeline minutes and bandwidth past the plan's allowance are added on top (Render changelog).
An Elements app is one app on one server. Jobs and cron ship with the app framework and deploy with it. The job queue is a table in your Postgres database, so a job enqueued inside a transaction is committed or discarded with the rest of it. Cron schedules are declared in the project's index.ts, and Postgres elects one machine to fire each tick (jobs, transactions). Realtime updates travel over Postgres LISTEN and NOTIFY, so a chat or a live dashboard needs no Key Value store either (channel). The web server, the job worker, the scheduler, Postgres and a load balancer that issues and renews TLS certificates all run on the server you already rent (what deploy does).
What you pay Elements is a price per machine, known up front, and nothing is metered: builds, requests and background work never appear on an Elements bill (pricing, licenses). Adding a job, a cron schedule or a live page to the app adds no new service to either bill.
Deploys Pick Up Where the Last One Left Off
Every Render deploy runs your build command in Render's build pipeline, and the time it takes is counted in pipeline minutes. A build can run up to 120 minutes and a pre-deploy command up to 30, and each service has one active build at a time: a new push cancels the build in progress (build pipeline). When the build is done, Render boots a new instance and moves traffic to it once it is ready. Every deploy builds and boots a new instance, however small the change (deploys).
Elements has no build pipeline to queue for, and no pipeline minutes to count. The server you deploy to runs its own project server, which still holds the build state from the previous deploy. Running elements deploy links your project server to that one over SSH; they work out which files differ and send just those, often a few KB, and the server rebuilds only what they affect. No new instance is booted: the release switches over by renaming a directory atomically, so there is no restart pause and no warm-up. A fresh machine takes a few seconds the first time, and later deploys usually land in under a second (what deploy does).
Tests Run Against a Migrated Copy Before Your Data Moves
A release that changes the schema can pass every test against the old schema and still break once the migration runs. Render's pre-deploy command is where it suggests running migrations, and if the command fails the service keeps running its previous deploy (deploys). That command runs against your real database. To test a migration before it touches your data, you would provision a second database, migrate it first, point the tests at it, and run them against the build being released, all inside that one command.
In Elements that sequence is the deploy itself, with nothing to script. Step one: each machine compiles the release, and the first machine migrates a separate test database. Step two: each machine runs your tests against that migrated copy. Step three, reached only if every test passes: the first machine migrates the app database, all pending migrations in one transaction. Fail at any step, by compile error, test or migration, and the release stops while users keep the previous one (deploy, tests, migrations). elements deploy -json reports every result from every machine in one answer.
Your Agent Finds the Broken Build Before It Leaves Your Machine
An agent improves through correction: learning what it got wrong the moment it gets it wrong. Render asks it to learn a platform first, with its service types, a Blueprint in YAML, build, pre-deploy and start commands, and environment settings kept in Render's dashboard. Each is another concept to look up and another seam between the code and the host. Some layer between the code and the machine is required, and nobody wants an agent writing its own process manager, but past that plumbing every platform concept costs an agent more to learn than it saves.
On Render, a build that fails is reported in Render's build log, after the push and after the build has run. Your agent reads that log to learn what went wrong, then pushes again.
With Elements there is no build log to wait for, because the build your server runs has already passed on your computer. On every save, the build state is updated almost instantly, since the project server holds the build graph and build state in memory: it builds in milliseconds and answers agents and humans in microseconds (build). Before any push, elements build -json gives your agent every build error, from failing tests and migration problems to what type checking and program analysis find, all in one reply. The deploy itself is SSH to an Ubuntu server, standards the agent already knows, and Elements, as one coherent system, checks the app the same way on your laptop and on the server. A local build with errors also blocks elements deploy from starting (what deploy does).
Pick the Server and the Database Separately
Render sells the server and the database, both on its own infrastructure. With Elements you choose each one on its own terms:
- Servers: Hetzner, DigitalOcean, AWS, or anyone else whose Ubuntu machines you can reach by SSH (setup).
- Database: the Postgres that the first deploy installs and starts on the server, which is plenty for a prototype or one machine. Past that, or if you want someone else running backups and scaling, Elements points to a hosted Postgres like Amazon RDS or DigitalOcean Managed PostgreSQL through the
DB_HOSTsetting (setup). - CDN: any of them, or none. Asset URLs carry a content hash and are served as immutable, so CloudFront, Cloudflare, Fastly or Bunny can front them (load balancer).
A second server makes a staging environment (environments), and more servers pointed at one shared Postgres share the traffic.
Changing Servers Is a Config Change
Leaving Render means recreating each worker service, cron job service and Blueprint on the new host. An Elements app has no such inventory to rebuild. Its jobs and cron schedule live in the code, next to the build and the tests, and the code is plain TypeScript, HTML, CSS and SQL that runs on Node against standard Postgres. A move is one edit and one command: put the new server's address in config.jsoc, then deploy (walkthrough). If the data sits in the bundled Postgres, export it as SQL with elements db dump and load it on the other side (database cli). The MIT license covers @elements/app and the rest of the runtime packages (licenses).
Questions
What is the difference between Elements and Render?
Render is a hosting platform: it builds your app from a Git repository, runs it on its infrastructure, and bills each web service, worker, cron job and database as a separate service. Elements is not a host. It builds your app and ships it, jobs, cron and Postgres included, to a single server you rent wherever you like.
Is Elements a Render alternative?
Yes, minus the separate worker and cron services. On one rented server, Elements runs the job worker, cron, Postgres and a load balancer that issues and renews TLS certificates next to the app, and it handles the build, tests and deploy that put them there.
How much does Elements cost compared to Render?
Render charges a workspace plan plus each service's instance, and bills build minutes and bandwidth past the plan's allowance (Render pricing). Elements charges a price per machine, per month, with nothing metered (Elements pricing), and the server itself is billed by the provider you rent it from.
Does Elements run database migrations on deploy like Render's pre-deploy command?
Yes, and it tests them first. Every deploy migrates a separate test database, runs your tests against it on every machine, and only then migrates the app database in one transaction. A failure at any step stops the release and the previous one keeps serving.
Do I need separate services for background workers and cron with Elements?
No. Jobs and cron are part of the default app framework that ships with Elements and run on the same server as the app. The job queue lives in your Postgres database, and Postgres picks one machine to fire each cron tick.