For developers
How to release or roll back Neo
How operators publish a safe release, reverse it, and investigate common problems.
Deployment topology
flowchart TB Internet --> Proxy[Coolify HTTPS proxy] Proxy --> Parent[withneo.app] Proxy --> Commerce[shop.withneo.app] Proxy --> Homes[homes.withneo.app] Proxy --> App[app.withneo.app] Proxy --> API[api.withneo.app] Proxy --> Docs[docs.withneo.app] Parent --> Container[Neo Node 24 container] Commerce --> Container Homes --> Container App --> Container API --> Container Docs --> Container Container --> PG[(Managed PostgreSQL)] Container --> Object[Private object storage] Container --> Providers[Certified provider adapters]
If the diagram does not render, its Mermaid source remains readable above.
The root Docker image runs as a non-root user, exposes port 3000, and uses /ready for health. All product hostnames may route to the same container. The Homes experience stays unavailable until its distinct route qualifies.
Release sequence
- Run the deterministic baseline and inspect the diff.
- Push the reviewed commit and wait for CI.
- Deploy the exact commit through the existing Coolify application.
- Confirm readiness and each host boundary.
- Run browser QA on public and protected-safe pages.
- Inspect logs for route, rendering, worker, database, and provider errors.
- Run live model/provider checks only when the change requires them and the runbook authorizes side effects.
Rollback boundary
Application rollback is safe only when the target code understands the current schema and durable queue records. Database migrations are forward-only; do not edit shipped migrations. If a release introduces external side effects, disable the relevant kill switch before rollback and reconcile ambiguous commands.
The historical SQLite cutover has a stricter rule: after PostgreSQL accepts writes, a stale SQLite backup cannot become the runtime without an explicitly reviewed reverse reconciliation.
Troubleshooting by symptom
| Symptom | First checks |
|---|---|
| Container unhealthy | /ready, database connectivity, migration completion, startup validation. |
| Callback rejected | Canonical API URL, selected adapter, signature secret, request size, provider configuration. |
| Message or command stuck | Queue counts, lease age, retry/dead-letter state, worker role, provider reconciliation. |
| Payment not confirmed | Signed callback receipt, reference/amount/currency/order match, provider status. |
| Payout blocked | Kill switch, recipient, held/available balance, certification, reconciliation case, provider limits. |
| Wrong public claim | Capability matrix, runtime flags, certification, production evidence, outcome-messaging rules. |
Operational safety
Do not publish provider evidence, credentials, customer data, private URLs, internal application identifiers, or raw callback payloads. Do not blindly replay ambiguous financial or courier commands. Keep callback ingestion and reconciliation available during incidents even when new external writes are disabled.
Dockerfiledocs/DEPLOY_COOLIFY.mddocs/PROVIDER_CERTIFICATION.mdsrc/dev-server.tssrc/durable-queue.ts
