Cloud Database & Compute Shootout

Eleven free plans. One recorded US-East run. Pick plans, then read the chart.

Free plans

Select a plan. The long note stays closed until you do.

Free-plan limits for the plans in view.
PlanStorageComputeDormancyHidden cost
Pixeltable Cloud50 GB media storage, 10 GB database storageHosted compute includedNo forced sleep or auto-pause; always-warm schema & endpointsZero. ffmpeg, Whisper, CLIP & vector indexing run in-schema; no external orchestrators or vector DBs needed.
RailwayShared container disk / persistent volume$5 monthly credit (approx. 500 execution hours total)Sleeps or shuts down when $5 credit exhausts; 24/7 Postgres burns out in ~20 daysRailway as Postgres: template runs raw PostgreSQL 16 container that drains the $5 credit 24/7. Zero built-in multimodal, vector indexing, or pipeline triggers.
RenderEphemeral container filesystem750 free instance hours/month (512 MB RAM)Spins down after 15 minutes of inactivity (50s cold start); Free Postgres deleted after 30 daysRender as Postgres: free tier PostgreSQL databases expire and are permanently wiped after 30 days! Free web services suffer 50s cold starts after 15m idle.
Cloudflare5 GB D1 SQLite, 10 GB R2 object storage100,000 Workers requests/day, 5M D1 reads/day, 5M Vectorize queries/moAlways warm across 300+ global edge locations; 0ms cold startsCloudflare D1 & Vectorize: Workers free plan has a hard 10ms CPU time limit. V8 isolates cannot run Python ML libraries (PyAV, Whisper, PyTorch). Must hop to Workers AI or external GPU clusters.
ModalEphemeral container disk + volume storage$30/month recurring compute creditContainers shut down when idle (zero cost while inactive; 1-2s container cold boot)Stateless: must maintain an external database and object store to persist state and query embeddings.
Neon1 GB storage per project100 compute unit (CU) hours/moCompute scales to zero after 5 minutes of idle (1-3s wake-up cold start)Requires external queue workers, object storage, and custom migration scripts for AI model updates.
Supabase500 MB database, 1 GB file storageShared compute, 500k Edge Function invocations/moProjects automatically paused after 7 days of inactivityExternal compute service required for heavy media transforms (Deno runtime cannot run ffmpeg/Whisper); manual vector backfill scripts.
Turso5 GB total storage500M row reads/mo, 10M row writes/moNo inactivity pause; always availableRequires external file storage for media and custom Python workers to encode vectors before insertion.
Prisma Postgres500 MB storageShared compute poolNo forced sleep during public betaRequires external worker processes for media processing and model inference; manual backfill scripts.
Convex1 GB file & document storage1 Million function calls/moNo dormancy pause on active free accountsRequires external HTTP compute service to run ffmpeg or local ML models; action/mutation hopping.
VercelEdge KV / Blob / Postgres (via partner integrations)100,000 serverless function executions/mo, 100 GB-hoursScale-to-zero serverless lambdas; cold starts on idle wakeStateless frontend platform: requires external database and background task workers for long-running ETL.

Warm latency

Lower is better. Bar length is the p50. A Worker reply and a SQL round trip are different operations.

0250500 ms
Warm latency. Lower is better. Bar length is the p50. A Worker reply and a SQL round trip are different operations.
RankPlanResultWhat was timed
1Cloudflare Workers11.6 mscompute. Min 10.7 ms. p95 14.1 ms. 200 OK.
2Railway Postgres22.1 msdatabase. Min 21.6 ms. p95 44.0 ms. 200 OK.
3Railway25.9 mscompute. Min 24.4 ms. p95 29.0 ms. 200 OK.
4Render27.0 mscompute. Min 22.5 ms. p95 30.7 ms. 200 OK.
5Render Postgres66.1 msdatabase. Min 64.6 ms. p95 131.6 ms. 200 OK.
6Neon Serverless PG68.3 msdatabase. Min 66.9 ms. p95 73.3 ms. 200 OK.
7Turso libSQL90.7 msdatabase. Min 83.4 ms. p95 118.9 ms. 200 OK.
8Vercel94.9 mscompute. Min 90.9 ms. p95 115.0 ms. 200 OK.
9Prisma Postgres98.6 msdatabase. Min 97.4 ms. p95 198.0 ms. 200 OK.
10Convex99.4 msdatabase. Min 82.5 ms. p95 125.4 ms. 200 OK.
11Pixeltable Compute104.4 mscompute. Min 102.8 ms. p95 105.1 ms. 200 OK.
12Supabase PostgREST116.2 msdatabase. Min 83.9 ms. p95 167.2 ms. 201 Created.
13Pixeltable Ingest128.3 msdatabase. Min 124.9 ms. p95 143.8 ms. 200 OK.
14Modal271.3 mscompute. Min 266.0 ms. p95 295.2 ms. 200 OK.

Stateless compute

Higher is better. Bar length is the burst rate.

0250500 req/s
Stateless compute. Higher is better. Bar length is the burst rate.
RankPlanResultWhat was timed
1Railway435.2 req/sFastAPI in Debian container. Warm p50 25.9 ms. ~2s (if configured to sleep; always-on consumes credits) 0.5 - 1.0 vCPU shared $5 trial credit / mo (~500 execution hours)
2Cloudflare Workers395.5 req/sJavaScript / Wasm isolate. Warm p50 11.6 ms. < 5ms worldwide (zero container overhead) 10ms CPU time per invocation (Standard Free plan ceiling) 100,000 requests/day
3Vercel238.7 req/sFastAPI / Python 3.11 serverless. Warm p50 94.9 ms. 200ms - 800ms on lambda scale-up 10s maximum execution duration (Hobby plan) 100,000 invocations/month
4Render128.4 req/sFastAPI in container (512 MB). Warm p50 27.0 ms. ~50 seconds after 15m idle sleep 0.5 vCPU shared 750 instance hours/month
5Pixeltable Compute56.1 req/sPixeltable Execution Engine + FastAPI. Warm p50 104.4 ms. None (always-warm managed endpoint) Shared community cluster compute 50 GB media + 10 GB database storage
6Modal27.3 req/sFastAPI ASGI mounted inside Modal Container. Warm p50 271.3 ms. 1.2s - 2.5s container initialization Customizable up to 64 vCPU & H100 GPUs $30/month recurring compute credit

Not timed: Neon, Supabase, Turso, Prisma Postgres, Convex

Point reads

Lower is better. Bar length is the p50.

0100200 ms
Point reads. Lower is better. Bar length is the p50.
RankPlanResultWhat was timed
1Cloudflare Workers11.6 msEdge V8 Isolate response
2Railway Postgres22.1 msDirect SELECT via TCP proxy
3Turso libSQL65.4 msSELECT 10 rows (HTTP pipeline)
4Neon Serverless PG65.7 msSELECT 10 rows (SQL proxy)
5Render Postgres66.1 msDirect SELECT via Virginia SSL
6Prisma Postgres90.9 msSELECT 10 rows (asyncpg pool)
7Convex99.4 msdb.query("docs").take(10)
8Supabase PostgREST111.4 msGET ?select=*&limit=10
9Pixeltable Query112.5 msTable select & filter query
10Modal186.4 msFastAPI ASGI GET /read

Not timed: Vercel

Single-row writes

Lower is better. Bar length is the p50.

0125250 ms
Single-row writes. Lower is better. Bar length is the p50.
RankPlanResultWhat was timed
1Railway Postgres67.0 msDirect SQL INSERT over TCP proxy PostgreSQL WAL commit
2Neon Serverless PG68.3 msDirect SQL INSERT over WebSocket/HTTP pooler ACID WAL flush to cloud storage architecture
3Pixeltable Ingest (Async Job)68.5 msImmediate HTTP ACK with Job ID + background DAG worker execution (background=True) ACID PostgreSQL record + immutable version snapshot
4Turso libSQL90.7 msHTTP pipeline POST execute with remote WAL sync SQLite WAL committed to primary writer
5Prisma Postgres98.6 msSingle SQL INSERT over asyncpg connection pool PostgreSQL WAL commit via edge pooler
6Convex99.4 msReactive mutation handler commit to document table Deterministic STM (software transactional memory)
7Supabase PostgREST116.2 msPostgREST HTTP POST with JSON body into Postgres 17 PostgreSQL synchronous commit WAL
8Pixeltable Ingest128.3 msVersioned table row insert + automatic computed column DAG trigger ACID PostgreSQL record + immutable version snapshot
9Render Postgres198.3 msDirect SQL INSERT over Virginia SSL PostgreSQL WAL commit

Not timed: Cloudflare, Modal, Vercel

Batch ingest

100 rows, one payload. Higher is better. Bar length is rows per second. Payloads are not one schema.

01,0002,000 rows/s
Batch ingest. 100 rows, one payload. Higher is better. Bar length is rows per second. Payloads are not one schema.
RankPlanResultWhat was timed
1Neon Serverless PG1,316 rows/sSingle multi-row SQL INSERT query via pooler 0.076 s.
2Railway Postgres1,107 rows/sMulti-row SQL INSERT (100 rows) via TCP proxy 0.090 s.
3Supabase PostgREST817 rows/sSingle JSON array POST to PostgREST endpoint 0.122 s.
4Render Postgres603 rows/sMulti-row SQL INSERT (100 rows) via Virginia SSL 0.166 s.
5Pixeltable Python SDK568 rows/sClient SDK insert() batch with schema validation 0.176 s.
6Prisma Postgres503 rows/sSingle multi-row SQL INSERT over pooled connection 0.199 s.
7Turso libSQL33 rows/sPipeline batch with 100 execute statements in 1 payload 3.052 s.

Not timed: Cloudflare, Modal, Convex, Vercel

Burst

50 workers, 100 requests. Higher is better. Bar length is requests per second.

0250500 req/s
Burst. 50 workers, 100 requests. Higher is better. Bar length is requests per second.
RankPlanResultWhat was timed
1Railway435 req/scompute. p50 88 ms. p95 197 ms. 100%. Pure lightweight container pass-through; zero database persistence
2Cloudflare Workers396 req/scompute. p50 66 ms. p95 239 ms. 100%. Global Edge V8 isolates; fastest burst p50 (66ms) with 0ms cold starts
3Railway Postgres375 req/sdatabase. p50 122 ms. p95 150 ms. 100%. Direct pooled SQL connections over public TCP proxy (c=50, about 100 requests)
4Vercel239 req/scompute. p50 161 ms. p95 303 ms. 100%. Serverless Edge scaling; parallel lambda function invocations
5Neon Serverless PG199 req/sdatabase. p50 186 ms. p95 428 ms. 100%. Fastest database write burst; direct SQL execution over pooler
6Supabase PostgREST175 req/sdatabase. p50 218 ms. p95 411 ms. 100%. PostgREST HTTP proxy directly writing into hosted PostgreSQL
7Convex137 req/sdatabase. p50 225 ms. p95 463 ms. 100%. Managed reactive backend mutation; 136 req/s transactional burst
8Render128 req/scompute. p50 298 ms. p95 559 ms. 100%. Free instance handled 50 concurrent requests without thread starvation
9Pixeltable Ingest (Async Job)97 req/sdatabase. p50 395 ms. p95 623 ms. 100%. background=True delivers immediate ACK with job_url, achieving 96.6 req/s burst throughput and 0% errors while executing full DAG in background workers
10Render Postgres71 req/sdatabase. p50 516 ms. p95 1107 ms. 100%. Direct pooled SQL connections over Virginia SSL (c=50, about 100 requests)
11Prisma Postgres58 req/sdatabase. p50 338 ms. p95 1427 ms. 100%. Pooled connection manager stabilized burst without pool exhaustion
12Pixeltable Compute56 req/scompute. p50 783 ms. p95 1492 ms. 100%. In-engine route execution on shared Community cluster; 100% success rate
13Turso libSQL31 req/sdatabase. p50 1225 ms. p95 1871 ms. 100%. Single remote writer lock in SQLite serializes high-concurrency writes
14Modal27 req/scompute. p50 1579 ms. p95 3113 ms. 100%. Serverless container queue scaling with container concurrency autoscaling
15Pixeltable Ingest14 req/sdatabase. p50 2416 ms. p95 5695 ms. 100%. 100% success rate under 50-burst write spike with widened Nginx burst=100 delay=50 (was 94% with 6% 429)

Extreme concurrency

c=100. Higher is better. Bar length is requests per second. Modal Async is about 100 completions; the other rows are about 200.

05001,000 req/s
Extreme concurrency. c=100. Higher is better. Bar length is requests per second. Modal Async is about 100 completions; the other rows are about 200.
RankPlanResultWhat was timed
1Railway Postgres535.5 req/sp50 152 ms. 0.37 s. 100%. Pooled SQL over the public TCP proxy. About 200 requests. max_connections=500 on that database.
2Cloudflare Workers288.8 req/sp50 225 ms. 0.69 s. 100%. Edge isolate response. About 200 requests.
3Pixeltable Ingest (Async)169.6 req/sp50 468 ms. 1.18 s. 100%. background=True HTTP response. About 200 requests. This is a different sample from the c=50 burst row at 96.6 req/s.
4Convex144.5 req/sp50 514 ms. 1.38 s. 100%. Document mutation. About 200 requests.
5Render111.6 req/sp50 800 ms. 1.79 s. 100%. Warm container HTTP. About 200 requests at 111.6 req/s, p50 800 ms.
6Render Postgres103.1 req/sp50 813 ms. 1.94 s. 100%. Pooled SQL over Virginia SSL. About 200 requests. A separate check, not this timed run, refused new sessions at connection slot 97.
7Railway97.2 req/sp50 673 ms. 2.06 s. 100%. Container HTTP. About 200 requests.
8Neon Serverless PG73.2 req/sp50 1211 ms. 2.73 s. 100%. SQL over the serverless proxy. About 200 requests.
9Vercel70.7 req/sp50 690 ms. 2.83 s. 100%. Serverless function invocations. About 200 requests.
10Supabase PostgREST67.5 req/sp50 1208 ms. 2.97 s. 100%. PostgREST writes. About 200 requests.
11Pixeltable Compute49.3 req/sp50 1663 ms. 4.06 s. 100%. Stateless /ingest/titles. About 200 requests.
12Modal44.9 req/sp50 1877 ms. 4.46 s. 100%. Container POST. About 200 requests.
13Turso libSQL31.4 req/sp50 2604 ms. 6.36 s. 100%. Remote SQLite writes. About 200 requests. The single writer serializes them.
14Modal Async (.spawn)20.5 req/sp50 2167 ms. 4.87 s. 100%. background_task.spawn(). 20.54 req/s over 4.87 s is about 100 completed requests, not 200. p50 2167 ms.
15Pixeltable Ingest (Sync)13.8 req/sp50 4980 ms. 14.48 s. 100%. Synchronous insert with the computed-column DAG. About 200 requests.

Not timed: Prisma Postgres

Separate checks

  • Microburst rate limit

    500 requests, c=350

    443 responses were 200. 57 were HTTP 429 RATE_LIMITED with retry_after 1 s.

    The ingress buffer is burst=100 delay=50.

  • Decompression bomb

    625 megapixels

    HTTP 400 in 0.63 s. Image size exceeds the 178,956,970 pixel limit.

    The image decoder rejects the file before the full bitmap is allocated.

  • Synchronous insert pool

    250 clients

    250 of 250 returned 200, at 13.2 req/s.

    The connection pool queued commits. This run recorded no dropped sockets.

  • Render Postgres connection ceiling

    100 client connections

    New sessions were refused at slot 97: remaining connection slots are reserved for superuser.

    That database’s max_connections is 100, with superuser slots held back. This is a different run from the pooled c=100 timing.

  • Async ingest at c=200

    400 requests, c=200

    400 of 400 returned 200, at 63.1 req/s.

    The HTTP handlers queued work. This run recorded no dropped sockets.

  • Async ingest at c=100

    About 200 requests, c=100

    169.6 req/s, p50 468 ms, 200 of 200 returned 200.

    The HTTP response returns a job id. The measured p50 of that response is 468 ms, not a few milliseconds.

Media throughput

Higher is better. Bar length is videos per second.

02550 vid/s
Media throughput. Higher is better. Bar length is videos per second.
RankPlanResultWhat was timed
1Railway (Container)37.1 vid/sIn-memory PyAV decode + thumbnail generation. p50 131 ms. Pure ephemeral computation in Docker container. Zero database persistence or vector search.
2Render (Container)14.6 vid/sIn-memory PyAV decode + thumbnail generation. p50 285 ms. Ephemeral container processing. Zero database persistence or vector search.
3Supabase Storage10.0 vid/sRaw S3-compatible video upload to bucket. p50 401 ms. Stores raw video file bytes only; cannot decode frames, transcribe Whisper, or index embeddings.
4Vercel (AWS Lambda)5.6 vid/sPyAV video decode on serverless function. p50 687 ms. Lambda cold starts and payload ceilings (4.5 MB body limit triggers 413 Payload Too Large on 1080p).
5Pixeltable Cloud (Async Queue)3.3 vid/sNon-blocking async job submission + background engine drain. p50 72 ms. Immediate HTTP return (72ms submission p50); background workers decode PyAV and maintain embedding indexes.
6Pixeltable Cloud (Sync Video)1.5 vid/sFull synchronous PyAV decode + R2 storage + versioned DB insert. p50 1966 ms. Full pipeline executes in-schema: video validation, frame decode, thumbnail upload to R2, PostgreSQL row insert.

Not timed: Cloudflare, Modal, Neon, Turso, Prisma Postgres, Convex

Same pipeline, one file

Pixeltable4.8s
Seven separate vendors48.5s

One schema, or several services

Open a row for the full note.

  1. Eliminates 3-5 external microservices, glue code, and synchronization failures.

  2. Absorbs concurrency burst spikes up to 96.6 req/s with zero external queue infrastructure to configure or pay for.

  3. Decoders like ffmpeg and OpenCV execute natively within the database lifecycle.

  4. Every writer automatically triggers transformations without manual job dispatch code.

  5. Eliminates index desynchronization and orphaned vector rows.

  6. Prevents database downtime, connection drops, and partial migration failures.

  7. Free tier applications don’t go dark or fail health checks unexpectedly.

  8. Avoids sudden production outages caused by monthly trial credit exhaustion.

  9. Zero risk of catastrophic 30-day database deletion.

  10. Allows end-to-end multimodal AI pipelines without hopping to external GPU clusters.

  11. Drastically lowers total cost of ownership (TCO) and operational surface area.

Methodology

Equal Geographic Footprint (US-East)

All live cloud benchmarks were executed from an independent client residing in AWS US-East (N. Virginia), targeting each provider’s respective US-East region to isolate cloud engine performance from transcontinental network variance.

Free-plan endpoints, no negotiated exemption

Each timed endpoint ran on that provider’s published free plan. A provider appears on a chart only when that path was timed. After the Nginx burst change (burst=100, delay=50), the recorded Pixeltable ingest burst had no 429s. Turso’s burst reflects its single-writer lock.

Payloads are small, and they are not one schema

Supabase rows are title and video_url. Neon, Turso, and Prisma rows are id, title, and body. Compute endpoints accept a title and body and do not persist a row. Compare a chart within one path. Do not treat a Supabase write and a Neon write as the same statement.

Code Complexity & Frankenstack Tax

Line counts and service counts were determined from complete working implementations of the same multimodal application (video frame extraction, audio transcription with Whisper, CLIP embeddings, and semantic query). Non-blank, non-comment lines of code.

Dormancy is part of the free plan

Render spins a free web service down after 15 minutes. Neon suspends compute after about 5 minutes of idle time. Supabase pauses a free project after 7 days without activity. Those clocks are properties of the plans. This page does not ping them.

Questions

Were all 11 plans timed on every chart?

No. Eleven free plans are compared on storage, compute, and dormancy. A latency, burst, or batch chart includes only the providers timed on that path.

Do these numbers update themselves?

No. The charts are one recorded run from a client in AWS US-East. To publish a new run, execute python3 scripts/mega_shootout.py on your machine and copy the figures you trust into this file.

Does Pixeltable replace these databases?

No. Use Neon, Supabase, Prisma Postgres, or Turso when the app needs their database. Use Pixeltable when inserting a row should run a media pipeline. The two can sit side by side.

How do these free tiers behave under extreme concurrency (c=100) or large payloads?

At c=100, Pixeltable Ingest Async completed about 200 requests at 169.6 req/s, p50 468 ms. Render’s web service on that same shape completed about 200 requests at 111.6 req/s, p50 800 ms. The c=50 async burst is a different sample, 96.6 req/s over 1.04 s. Modal Async (.spawn) is also a different sample: 20.54 req/s over 4.87 s, about 100 completions, p50 2167 ms. Vercel rejects a payload above 4.5 MB with HTTP 413. Pixeltable Cloud accepts uploads up to 100 MB.

How do Railway Postgres and Render Postgres compare on this run?

Railway Postgres point reads were 22.1 ms and the 100-row batch was 1,107 rows/s. At c=100 it completed about 200 SQL requests at 535.5 req/s. Render Postgres point reads were 66.1 ms and the batch was 603 rows/s. Its pooled c=100 run completed about 200 requests at 103.1 req/s. A separate Render check, opening 100 direct connections, was refused at slot 97.

What did the breaking-point checks record?

500 requests at c=350 produced 443 responses of 200 and 57 of HTTP 429. A 25,000 by 25,000 PNG was rejected in 0.63 s. 250 synchronous inserts all returned 200, at 13.2 req/s. 400 async requests at c=200 all returned 200, at 63.1 req/s.

Provider pages
pip install 'pixeltable[serve]'
See how it works