This guide applies to automated execution, quoting, portfolio automation, and other long-running trading systems. Strategy selection and profitability are outside the SDK's scope.
Health model
| Dependency | Healthy evidence | Response when unhealthy |
|---|---|---|
| Catalogs | WaitForCatalogs completed; symbol and scale resolve | Do not encode or submit |
| Managed book | Recent update, bid below ask, no refresh in progress | Pause book-dependent writes |
| Private orders | Recent event or successful bounded reconciliation | Reconcile before replacing |
| Balances | Recent Balances.List snapshot | Stop the affected side |
| Dead-man switch | Last armed response has safe time remaining | Stop new orders immediately |
| Event queue | No *errors.QueueOverflowError | Replace subscription and resnapshot |
Track book age/sequence, refresh and reconnect counts, owned open orders, reserved and available balance, mutation latency, rejected batch items, unknown outcomes, dead-man expiry margin, and reconciliation duration. Generic queues hold 1000 items; the managed book queue holds 200.
Deployment and shutdown
- Start with writes disabled.
- Hydrate catalogs and validate configured symbols.
- Start managed public feeds and private order/balance streams.
- Reconcile open orders owned by this process prefix.
- Arm
Orders.CancelAllAfterfor 10 to 120 seconds. - Enable writes only when all dependencies are healthy.
For shutdown: disable new orders, cancel owned IDs, confirm they disappear from Orders.ListOpen,
then close streams. Do not disarm the dead-man switch until cleanup is confirmed. Avoid
account-wide cancellation as ownership cleanup; filter process-owned client IDs first. Treat not_found from those targeted cancels as idempotent success and propagate every other error.
Troubleshooting
| Symptom | Safe action |
|---|---|
| Post-only rejection | Refresh the book and calculate a new catalog-aligned price |
| Insufficient balance | Refresh balances; reduce or disable the affected order flow |
| Stale/one-sided book | Pause writes until a valid snapshot |
| Mutation timeout | Query known client/request IDs before retrying |
| Missing fills | Use WaitForOrderTradesComplete |
| Realtime overflow | Replace the subscription, snapshot, and reconcile |
| Dead-man refresh failure | Stop writes and continue cleanup/reconciliation |
| Authentication failure | Stop; treat as configuration/policy, not transient transport |
Create status accepted is admission, not working state. Batch RPC success does not mean every
item was accepted.
Testing ladder
- Unit-test strategy math, rounding, limits, and reprice thresholds.
- Run SDK codec/service tests for invalid input and malformed outcomes.
- Compile all documentation snippets against local SDK source.
- Run public devnet books, trades, and candles.
- Run authenticated reads on a dedicated account.
- Gate mutations behind an explicit flag with unique IDs and targeted cleanup.
- Run bounded scheduled canaries and assert final open-order state.
Every mutation test needs a strict notional cap, total context deadline, deferred targeted cleanup,
and final ListOpen assertion.
Upgrade checklist
Pin prereleases exactly (github.com/Fabric-Labs/polyester-sdk-go@v0.1.0a35 here). Review
request/default/status/stream changes, run tests and snippet checks, run public reads, execute one
gated create-cancel-reconcile cycle, deploy canaries first, then roll out gradually. A model field
is not proof that the current codec sends it; verify the service/codec path.
Tested recipes
- Two-sided order management
- Production trading bot
- Portfolio tracker
- Examples
05,07, and10in polyester-examples-go