Deta Space Runtime Diagnostic Guide: Failures After Shutdown
Deta Space shut down in 2024. This guide maps observable app failures—504s, lost files, Drive pagination, WebSocket drops—to hard platform limits so you can mitigate or migrate.
03 Mar 2026, 15:35 UTC

The Problem
Deta Space shut down in 2024. No new deployments, updates, or support exist, but previously deployed Space Runtime apps may still be handling traffic, writing to Drive, or serving WebSocket connections. When one of these apps fails, you cannot open a support ticket or apply a patch. You must diagnose using only the last documented runtime behavior and whatever the platform still emits.
Useful takeaway: Treat every symptom as a mismatch between your code's assumptions and the platform's hard limits: 60-second edge proxy timeout, ephemeral filesystem outside the Drive mount, 10 GB per-app Drive cap, no background workers, and no hot-reload for secrets. The checks below map observable failures to those limits so you can decide whether to mitigate in code, migrate data, or decommission.
Recognizable Failure Modes
| Symptom | Likely Cause | Diagnostic Signal |
|---|---|---|
| HTTP 504 after ~60s, no app error logs | Edge proxy idle timeout (hard 60s) | Handler runs past 60s; proxy returns 504 before handler completes |
| File writes disappear after redeploy or scale-to-zero | Writes to working directory or /tmp instead of Drive mount | Files present during request; missing after space push or idle period |
| Drive list() returns only 1000 items | Pagination cap (max 1000 per call) | Missing last cursor in follow-up list calls |
| Environment variable changes not reflected | Secrets injected at container start only; no hot-reload | space secrets set succeeded but app reads old value until next space push |
| WebSocket disconnects after 60s inactivity | Same edge proxy idle timeout applies to WS | No traffic for 65s → connection reset; no app-level ping/pong |
| space push hangs or build errors | Implicit build step (npm run build or pip install -r requirements.txt) failing | Build logs show missing dependencies; no custom Dockerfile support |
| Drive write errors or ENOSPC | 10 GB per-app Drive quota exceeded | Drive SDK returns quota error; disk shows full |
Ordered Diagnostic Checks
Run these in sequence. Each check isolates a cause or eliminates a class of failures.
1. Verify the CLI and Runtime Baseline
Where: Local machine with an archived space binary (last known release v0.9.x).
Permissions: User-level execution; no elevated privileges.
Command:
space --version
# Expected: 0.9.x
# If missing: build from archived source; no official downloads remain.
Check: Confirm the binary runs. If space login fails, the control plane is unreachable and you are limited to inspecting already-deployed apps over SSH.
Risk: None for read-only version check.
2. Inspect the Deployed App Environment
Where: Against a live app name; replace my-app with your app.
Permissions: Requires prior space login and app ownership.
Command:
space ssh my-app -- env | grep -E 'DRIVE|PORT|SPACE_'
# Expected: DRIVE_MOUNT_PATH=/mnt/drive, PORT=8080, SPACE_APP_NAME=my-app
Check: Verify DRIVE_MOUNT_PATH exists and is writable. If missing, the Drive volume failed to mount and nothing can persist.
Risk: SSH requires network access to any remaining Deta infrastructure.
3. Test the Request Timeout Boundary
Where: Deploy a throwaway handler to a test app.
Risk: Consumes one app slot; delete the test app afterward.
Handler example (Node.js):
// timeout-test.js
export default async function handler(req) {
await new Promise(r => setTimeout(r, 65000)); // 65s
return new Response('done');
}
Deploy: space push timeout-test (package.json main field points to timeout-test.js).
Test: curl -v https://timeout-test.deta.app/
Expected: 504 Gateway Timeout at roughly 60s, with no handler body. This confirms the edge proxy limit is active and unconfigurable.
4. Validate Drive Persistence and Pagination
Where: Inside the app via SSH or a deployed one-off script.
Commands:
# List first batch
space ssh my-app -- deta drive list --limit 1000
# Record the 'last' cursor from the response
space ssh my-app -- deta drive list --limit 1000 --last ""
# Expected: second call returns remaining items beyond the first 1000
Check: First call returns 1000 items plus a cursor. Second call returns the rest. If your code omits the cursor, it will miss data.
5. Confirm WebSocket Idle Disconnect
Where: Client machine with wscat or browser console.
Test: Connect to wss://my-app.deta.app/ws, send no frames for 65s.
Expected: Connection closes around 60s. The proxy terminates TCP; no server-side close event fires.
6. Check Drive Quota and Filesystem
Where: SSH into the app.
Command:
space ssh my-app -- df -h /mnt/drive
space ssh my-app -- du -sh /mnt/drive
# If Use% is above 90% or size approaches 10 GB, quota is the blocker
Check: Drive is flat—keys with slashes are single file names, not directories. There is no recursive delete; remove keys individually via the SDK.
Fixes Tied to Findings
| Finding | In-Code Mitigation | Migration Action |
|---|---|---|
| Handler exceeds 60s | Offload long work to external queue; return 202 immediately; poll or webhook for result | Rewrite as async job on Fly.io, Railway, or Cloudflare Workers |
| Writes lost on redeploy | Target DRIVE_MOUNT_PATH for all persistent writes; never ./data or /tmp | Bulk-export Drive via SDK to S3 or GCS |
| Drive pagination missing data | Implement cursor loop: while (res.last) { res = await drive.list({ last: res.last }) } | Use same loop in export script; verify total count |
| Secrets not updating | After space secrets set, always run space push; automate in CI | Migrate secrets to target platform secret store |
| WebSocket idle disconnect | Send application ping every 30s; add client reconnect logic | Move WebSocket to platform with configurable idle timeout |
| Build step failing | Validate package.json build script or requirements.txt; no system packages | Containerize app with multi-stage Dockerfile for target platform |
| Drive quota exceeded | Implement TTL cleanup and delete expired keys via drive.delete() | Export all Drive data before writes are blocked; no bulk export tool exists |
Escalation Criteria
Stop debugging and migrate when any of these are true:
- Control plane unreachable: space login fails or space apps returns an error. You cannot deploy fixes or read logs.
- Drive mount missing: DRIVE_MOUNT_PATH is absent from env or /mnt/drive does not exist. Data is already at risk.
- Repeated 504s on critical paths: You cannot refactor to async within days and business impact exceeds migration cost.
- Quota full and cleanup impossible: Drive is at 10 GB and SDK delete rate is too slow.
- Security exposure: App handles PII or payments on an unpatched runtime with no TLS rotation, WAF, or DDoS protection.
Limitations and Verification
All behaviors reflect the last public runtime (2023-2024). Deta published no SLA, no Drive durability guarantees, and no bulk export tooling. The CLI is unavailable from official sources; verify any binary against archived releases before trusting it.
Practical verification checklist:
- Confirm space --version outputs 0.9.x.
- Run space ssh -- env and verify DRIVE_MOUNT_PATH.
- Deploy the 65s sleep handler; observe 504 at 60s.
- Insert 1500 Drive keys; paginate with the last cursor; confirm a 1000/500 split.
- Open a WebSocket; idle for 65s; confirm disconnect.
If any check fails, the runtime has diverged from documented behavior. Treat all other assumptions as unverified.
Migration Path Outline
Because no fixes are possible on the platform, each diagnostic endpoint is a migration trigger. Minimal viable migration:
- Export Drive: Script drive.list() pagination and stream each file to S3, GCS, or Azure Blob, preserving key names as object keys.
- Rewrite request handlers: Move to Cloudflare Workers, Fly.io Machines, or Railway with Docker deployment.
- Replace WebSocket: Use PartyKit, Ably, or raw WebSocket on Fly.io with a custom idle timeout.
- Replicate secrets: Run space secrets list and import values into the target platform secret store.
- Cut DNS: Update the CNAME from .deta.app to the new host and monitor for 48 hours.
No rollback exists for the platform itself. The only practical rollback is keeping the old app running while the new one validates, but the old app may vanish without notice.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.