What is the best Symfony hosting in 2026?
Symfony runs on any PHP host, but an application with Messenger consumers, a scheduler and a compiled container cache needs a platform that models a build step and long-running processes. Render at $7/month and Railway at $5/month plus usage do both; Fly.io is cheapest at roughly $2/month if you are content to operate your own database.
Granite — our own platform — is $9/month with $15 of usage credits and puts the app, its MySQL or Postgres, its Valkey and its consumers in one project. For a small Symfony site with no queue, shared hosting beats every option on this page, and we say so more than once below.
Last updated 1 September 2026
Symfony deployments divide cleanly into two kinds, and confusing them is where most of the pain comes from. The first is a site: controllers, Twig, a database, deployed by uploading files. Shared hosting runs that perfectly well and costs almost nothing.
The second is an application: Messenger consumers processing a queue, a scheduler firing recurring tasks, Doctrine migrations that must run once and not once per replica, and a container cache that has to be compiled during a build rather than by the first unlucky visitor. That version of Symfony needs a platform that understands build steps, release commands and worker processes — and the difference in hosting cost between the two is much larger than the difference in code.
Unlike Laravel, Symfony has no first-party hosting platform to anchor the comparison, so what follows is general-purpose platforms judged on how well they fit the framework's assumptions.
The short version: Render and Railway are the smoothest managed starts, Fly.io is the cheapest if you are content to run your own database, and Granite — our own platform — fits when the app, its MySQL or Postgres, its Valkey and its consumers should live in one project. If your Symfony project is a small site with no queue, shared hosting beats every option on this page and we will say so more than once.
How much does Symfony hosting cost?
| Provider | From /mo | Free tier | Managed DB | Persistent disk | Deploy from |
|---|---|---|---|---|---|
| Fly.io | ~$2 | Postgres (unmanaged app) | Dockerfile, buildpack | ||
| Railway | $5 | yes ($1 credits) | Git, Dockerfile, template | ||
| Render | $7 | yes (spins down) | Git, Dockerfile | ||
| Granite | $9 | from Advanced | Git, Docker image | ||
| Koyeb | $29 | limited | Serverless Postgres | Git, Dockerfile | |
| Google Cloud Run | usage-based | yes (monthly allowance) | via Cloud SQL | no (use GCS) | Container image |
Entry prices as published by each provider on 1 September 2026, sorted cheapest first. Usage, bandwidth and databases are billed on top almost everywhere — treat this column as a starting point, not a monthly bill.
PaaS, serverless or a plain VPS?
Shared hosting deserves the first mention, as it does for Laravel, because for a large share of Symfony projects it is genuinely adequate rather than a compromise. Point the document root at public/, upload a build, and a content-driven site works. The line is the same one: the first Messenger consumer, or the first scheduled task that matters, turns a cheap host into an evening's work per deploy.
A managed platform is where an application with a queue belongs. What you are buying is not the ability to execute PHP — that is everywhere — but a build step where composer install and cache:warmup can run, a release phase for migrations, and long-running processes for consumers, with a managed database next to them.
Serverless fits Symfony awkwardly for a structural reason. A consumer must run continuously by definition, so it cannot scale to zero; you end up with a request-driven web tier plus an always-on worker, at which point much of the appeal has gone. It remains reasonable for a stateless API with genuinely bursty traffic, especially if the container ships a pre-warmed cache.
Content-driven site, no consumers, no scheduled work that matters, rare deploys
Shared hosting
Cheap and adequate, right up until the first background message.
Any cPanel host
Messenger consumers, a scheduler and migrations on every release
Managed platform
Build step, release phase and workers as first-class things, beside a managed database.
Granite · Railway · Render
Stateless API, bursty traffic, and you are already inside GCP
Serverless
Free while idle — with the cache warmed in the image and consumers hosted elsewhere.
Cloud Run · Koyeb
What does each platform actually give you?
Fly.io
- Best for
- Teams comfortable operating their own database who want several regions and per-second billing.
- Pricing
- Pay as you go. The smallest shared-cpu-1x machine with 256 MB RAM works out at roughly $2.02/month, billed per second.
- Takes your Dockerfile, so the PHP version, the extensions and whether you run PHP-FPM or FrankenPHP are entirely your decisions.
- Multi-region deployment and Anycast routing are first-class.
- Per-second billing, so stopped machines cost only storage.
- MySQL or Postgres is a Fly app you run and back up yourself — for Symfony, where Doctrine is the centre of the application, that is a real commitment.
- Messenger consumers and the scheduler are processes you define and supervise rather than platform features you enable.
- No free tier for new organisations since October 2024.
Railway
- Best for
- Getting Symfony, MySQL and Redis running together without deciding anything up front.
- Pricing
- Billing is per second of actual usage against a monthly minimum: $5 on Hobby and $20 on Pro, each including that much usage credit. The free plan is a 30-day trial with $5 of credits and $1 a month afterwards, capped at 1 vCPU and 0.5 GB per service. Pro includes unlimited workspace seats.
- Databases and Redis sit alongside services in the same project and reach each other privately.
- Workers and cron are ordinary resource types, so Messenger and the scheduler have somewhere proper to live.
- A free plan and a 30-day trial for evaluation.
- Usage-based billing on top of the base fee is hard to forecast.
- Hobby covers a single developer. A second person on the project moves you to Pro and its $20 monthly minimum.
Render
- Best for
- A conventional Symfony production setup with a predictable monthly bill.
- Pricing
- Free web services are available but spin down after 15 minutes without traffic. The cheapest paid instance, Starter, is $7/month for 0.5 vCPU and 512 MB RAM.
- Release commands are first-class, so doctrine:migrations:migrate runs once per deploy in the right place.
- Background workers and cron jobs cover Messenger consumers and the scheduler cleanly.
- Managed Postgres and Redis, plus a real free tier for evaluating.
- Managed MySQL is not offered, so a Symfony project whose Doctrine mapping assumes MySQL either moves to Postgres or looks elsewhere.
- Free services spin down after 15 minutes idle.
Granite
- Best for
- A Symfony application whose database, cache and consumers should sit in the same project as the web app.
- Pricing
- Hobby is $9/month and includes $15 of monthly usage credits. Advanced is $39/month with $50 of credits, Professional $149/month with $200. Every plan has unlimited workspace seats.
- Managed MySQL as well as Postgres, plus Valkey for Messenger transports and cache — all over internal DNS with no public endpoint.
- Web app, Messenger consumer and scheduler are three resources built from one image, so a consumer can never run older code than the site that enqueued the message.
- Cron jobs are a resource type, which is what the Symfony scheduler wants.
- S3-compatible storage with a CDN for uploads, and flat plan pricing that does not move with traffic.
- No free tier — the cheapest way in is $9/month, against genuinely cheap shared hosting.
- Nothing here is Symfony-aware: cache warmup, migrations and consumer restarts are steps you define yourself.
- Fewer regions than the hyperscalers, and no multi-region routing yet.
Koyeb
- Best for
- Low-traffic Symfony apps where paying nothing while idle matters more than anything else.
- Pricing
- Pro is $29/month plus compute and includes $10 of it; Scale is $299/month including $100. Serverless Postgres has a free tier of 5 hours a month at 0.25 vCPU, 1 GB RAM and 1 GB of storage, after which the smallest always-on instance is $29.76/month plus $0.50 per GB stored.
- Scale-to-zero with edge locations included.
- Managed Postgres available on the platform.
- The highest entry price of the managed options here.
- Scale-to-zero does not apply to a Messenger consumer, which has to keep running — so the saving covers only part of the bill.
Google Cloud Run
- Best for
- Stateless Symfony services with bursty traffic, for teams already invested in GCP.
- Pricing
- No monthly fee. You pay per request and per resource-second, with a monthly free allowance. Cloud SQL and networking are billed separately.
- Scales to zero and has effectively no ceiling.
- Takes any container image, so your PHP version and extensions are pinned by your own Dockerfile.
- A warmed Symfony cache baked into the image means the cold start is a PHP boot rather than a compile.
- No persistent disk, so anything under var/ that you expected to persist — and every upload — has to move to a bucket first.
- Messenger consumers and the scheduler do not fit a request-driven model and need separate infrastructure.
- Database, cache and secrets are separate GCP products you assemble and bill separately.
What does a Symfony app need from a host?
- A real build step
- composer install --no-dev --optimize-autoloader and cache:warmup belong in the image build, not in the container's start command. A Symfony application with a cold cache compiles the service container on the first request, which means the first visitor after every deploy pays for it — and on a read-only or ephemeral filesystem it may not work at all.
- APP_ENV=prod, and the debug toolbar off
- The single most consequential environment variable here. In dev, Symfony recompiles the container on changes, logs verbosely and serves the profiler — all of which are catastrophic in production, both for performance and because the profiler exposes your configuration. Set it explicitly rather than relying on a default.
- Migrations as a release step
- doctrine:migrations:migrate --no-interaction must run once per deploy, after the build and before the new version takes traffic. In the start command every replica races against the same schema. Look for a release command or pre-deploy hook, and treat its absence as a genuine limitation rather than an inconvenience.
- Messenger consumers restart on deploy
- messenger:consume loads the container once and keeps it in memory, so a consumer started before a deploy keeps running the old code afterwards. Every deploy must end with messenger:stop-workers, and the platform has to restart the process. This produces the most confusing class of bug in a PHP application: the site is correct and the background work is a week stale.
- The scheduler needs real cron
- Whether you use Symfony Scheduler or plain cron entries, something has to fire on a timetable outside the request cycle. A platform with cron as a resource type makes this configuration; without one you end up running a sleep loop in a container and hoping it never dies quietly.
- APP_SECRET, exactly once
- It signs cookies, CSRF tokens and remember-me credentials. Generate it once and supply it as an encrypted environment variable; a value that changes per deploy or differs between replicas invalidates sessions and CSRF tokens in ways that look like a random, intermittent bug.
- var/ is not storage
- var/cache and var/log must be writable, but nothing in them should be expected to survive — the container filesystem is discarded on deploy and not shared between replicas. Logs belong on stdout where the platform collects them, and user uploads belong in object storage through Flysystem, not under public/.
- Trusted proxies behind the load balancer
- Every platform here terminates TLS in front of your container, so Symfony sees plain HTTP and generates http:// URLs, breaking absolute links and redirects in ways that present as a certificate problem. Configure framework.trusted_proxies so the X-Forwarded headers are honoured. It is two lines and it reliably costs an afternoon the first time.
- PHP-FPM or a worker runtime
- Classic PHP-FPM boots the framework on every request and keeps a pool of children, each holding its own copy. A worker runtime such as FrankenPHP boots once and serves many requests, which is markedly faster and changes the memory profile — but it also means your code must not leak state between requests. Decide before sizing the instance, because the two shapes want different plans.
Where do background jobs and queue workers run?
Messenger decides this, and the transport decides the bill. doctrine:// keeps the queue in the Postgres you already pay for and is enough for most projects; redis:// against a managed Valkey buys you throughput and blocking reads; amqp:// means running RabbitMQ, which is a service to operate rather than a line in a config file. The consumer is a long-lived process, bin/console messenger:consume async, from the same image as the web app. On Granite that is a worker resource with no public domain. The --time-limit and --memory-limit flags are still worth setting — PHP leaks over long runs — but you no longer need supervisor to restart the process afterwards, because exiting is the platform's cue to start it again.
How do scheduled tasks and cron work?
Symfony's Scheduler component moves recurring work into Messenger, dispatched by a consumer running messenger:consume scheduler_default. That is one process by design, and running two of them dispatches everything twice, so keep it at a single replica — the same trap as a crontab baked into an image that you then scale. The platform alternative is a cron-job resource: on Granite it runs bin/console app:send-reminders on a cron expression as exactly one container, takes no replica count, and lets you choose Forbid or Allow when a run overlaps the next slot. Its output goes to that resource's own log, which is the practical reason to prefer it: a failed reminder is visible without grepping the web app's stream.
Is Postgres managed, and what about backups?
Managed on Render, Railway, Koyeb and Granite; on Fly it is an app you deploy and maintain. Granite takes scheduled backups into external storage and support can run point-in-time recovery for Postgres on request, without a published interval, so ask if you need a stated RPO. Databases have no public endpoint: Doctrine connects over internal DNS, and you connect with novps port-forward database <id> -l 5432. PHP opens a connection per request rather than holding a pool, so the pressure comes from PHP-FPM children — thirty per replica across three replicas is ninety potential connections, which a small managed node will not grant.
How do deploys and migrations work?
A push builds the image, or the platform watches a Docker tag you push. composer install and cache:warmup belong in the build; doctrine:migrations:migrate belongs in a step that runs once per deploy. Render and Railway have a release command for it; on Granite you run it from the resource's Console tab or over a forwarded database port before the new image rolls out. In the container entrypoint it becomes a race between replicas. Remember the consumer as well: it holds the old code until its process is replaced, which is exactly why --time-limit is not optional. A message serialised by the new web app and read by a consumer still running last week's classes fails in a way that is genuinely tedious to diagnose.
What does it actually cost per month?
PHP-FPM behind a web server, one Messenger consumer and a small Postgres, as of 1 September 2026. Fly.io is $3.32 for each 512 MB machine, with the database your responsibility. Render is $7 for the web service, $7 for the consumer and $6 for a 256 MB Postgres — $20, and no broker at all if the transport is Doctrine. Railway bills per second against a $5 monthly minimum on Hobby. Granite is $9 with $15 of credits shared across the three, and choosing the Doctrine transport over a Valkey node keeps $8 a month of those credits for the application instead — the cheapest queue is the database you were already paying for.
So which should you pick?
A content site with no queue. Shared hosting, honestly. Nothing on this page will serve you better for the money until the application grows a background consumer.
A conventional production app, least ceremony. Render. Release commands, workers and cron behave the way the Symfony docs assume — provided you are on Postgres rather than MySQL.
Fastest path to a running stack. Railway, which will have Symfony, MySQL and Redis talking to each other the same afternoon.
Symfony as one part of a larger system. This is where we would argue for Granite. Managed MySQL — still the default assumption in a great many Symfony projects — sits beside the app with Valkey for Messenger transports and cache, all over internal DNS with no public endpoint. The web app, the consumer and the scheduler are three resources from a single image, so nothing can drift out of sync, and cron is a resource type rather than a workaround. Flat plans from $9/month with $15 of usage credits.
Running other PHP or JavaScript services beside it? The Laravel and Next.js comparisons cover the same platforms with different conclusions, and the app platform page covers workers and cron jobs in detail.
Hosting for other stacks
Six ways to run a Go binary, from a $2 machine to scale-to-zero — and why Go stays cheap longer.
Seven options weighed on the things Django actually needs: media storage, a real Postgres, Celery workers and enough memory for gunicorn.
Vercel and six alternatives, weighed on the things that actually break when you self-host: ISR across replicas, image optimization and build-time env vars.
Six ways to run an Express, NestJS or Fastify service — weighed on the event loop, the connection pool, and what a long-lived process costs while it waits.
Six platforms plus Kamal, weighed on what Rails really needs: a release phase for migrations, a job runner, Active Storage and enough memory for Puma.
Laravel Cloud and six alternatives, weighed on queue workers, the scheduler, writable storage and the caches you must rebuild on every deploy.
Seven platforms for Django, Flask, FastAPI or a script with no HTTP port at all — and how to tell which of those you are actually deploying.
Six platforms weighed on what an ASGI service actually needs: worker processes, connections that stay open, and a database pool that does not multiply out of control.
Seven options for the framework that ships no opinions — weighed on the WSGI server you have to bring, the session key you must keep stable, and the extensions that decide the rest.
Seven platforms for a framework that renders on every request — weighed on streaming, adapters, and how far the loaders sit from the database.
Six platforms weighed on what the JVM actually asks for: memory it is allowed to use, a container that knows its own limits, and a start-up you can afford to repeat.
Six places to run a container image, compared on what actually bites: architecture mismatches, registry access, signal handling and the volume you assumed would still be there.
Five ways to serve HTML that is already written — and an honest note about which of them we are not the right answer for.