Case Notes: MTRobot — Building a Multi-Tenant Algo Trading SaaS on MT5

Case Notes: MTRobot — Building a Multi-Tenant Algo Trading SaaS on MT5

Engineering notes on building a multi-tenant algo trading SaaS — MT5 integration, execution isolation, real-time streaming, and security constraints. What we learned building production trading infrastructure.

Building a platform that executes live trades on behalf of users is a different category of problem from most SaaS products. Latency matters. Failures have real financial consequences. And the security model has to be watertight — users are handing you credentials to their brokerage accounts.

These are the engineering notes from building MTRobot. For the full product context, see the MTRobot case study. For broader context on why trading systems require a different engineering approach than typical software, see Trading Systems & Platforms.


MT5 integration is not a simple API call

MetaTrader 5 is the dominant retail and semi-institutional trading terminal globally, but its API is not a modern REST interface. Integration requires running an MT5 terminal process, maintaining a persistent connection to the broker’s trade server, and handling a session model that was designed for a desktop application — not a cloud multi-tenant service.

Key integration challenges we worked through:

Session persistence. MT5 connections drop on inactivity (default timeout: 30 seconds), on broker-side maintenance windows (typically daily, 00:00–00:05 server time), and on network hiccups. Every user agent needs a reconnect loop that is robust — with exponential backoff and jitter — but doesn’t spam the broker’s server. A naive reconnect loop can get the IP rate-limited.

Per-user terminal isolation. You can’t run one MT5 terminal for all users. Each user’s connection is a separate session to a specific broker server. We run isolated containers — each user’s trading agent gets its own process, its own credentials scope, and its own execution context. This is not a performance optimization; it’s a correctness requirement.

Order execution timing. Market orders need to land within the broker’s execution window. Slippage and requotes are real at market open and during news events. The platform has to handle partial fills, rejected orders, and broker-side execution errors gracefully — and log everything for the user to see.

User AUser BUser CContainer AMT5 terminal + agentContainer BMT5 terminal + agentContainer CMT5 terminal + agentBroker ATrade serverBroker BBroker Cisolated — no shared state
Each user gets an isolated container with its own MT5 terminal. No shared state between users at the execution layer.

Execution isolation is a hard requirement

When one user’s robot has a bug or generates an unexpected signal volume, it must not affect any other user’s execution. This seems obvious but requires deliberate architecture.

Each trading agent runs in a dedicated container with enforced resource limits (CPU, memory, network). If an agent goes into a retry loop or starts generating excessive orders, it gets isolated and flagged — it doesn’t create load for other users. Circuit breakers on the order submission path protect the broker connection from being overwhelmed.

This isolation also matters for security: a compromised agent context can only affect the account it has credentials for. There is no shared state between user agents at the execution layer.

The pattern here is similar to what makes production ML systems robust — see Applied AI Is Not a Web Service for why shared state is the root cause of most cascade failures.


The security constraint: trading access only

This is a design decision we committed to early and it shaped everything downstream. The platform requests only trading permissions from MT5 — it cannot initiate withdrawals, transfer funds, or modify account settings. This is enforced at the MT5 API permission level, not just at the application layer.

For users, this is the critical trust signal: even if something goes wrong, the platform cannot take money out of your account. The worst case is a losing trade, which is a normal trading outcome — not an unauthorized transfer.

Credential encryption, session token rotation, and isolated execution contexts all follow from the same principle: minimize the blast radius if any part of the system is compromised.


Real-time streaming without drowning the client

Trading accounts generate a continuous stream of events: tick updates, order state changes, position updates, equity changes. Sending everything raw to the frontend would overwhelm the browser and make the UI unusable.

The approach: a server-side aggregation layer that normalizes the event stream, deduplicates redundant updates, and emits batched snapshots at a cadence the frontend can render smoothly.

MT5 raw eventsticks, orders, fills~100 events/secAggregation layerDeduplicate redundant updatesNormalize to state snapshotsThrottle to render cadenceClient snapshotsbalance, positions, PnL~2 updates/secBrowser UIsmooth renderreconnect-safe
100 raw MT5 events/sec → aggregation → 2 meaningful state updates/sec for the client.

The client receives meaningful state updates — balance changed, position opened, trade closed — rather than raw market ticks. This also means the UI stays accurate even when the user reconnects after being offline. The platform maintains the authoritative state server-side; the frontend just renders the latest snapshot.


Onboarding UX for non-technical traders

The platform’s core audience is traders who understand markets but are not software engineers. They know what MetaTrader 5 is and they have a brokerage account — but they may have never connected an external service to their terminal before.

The onboarding flow needed to make a technically complex operation (establishing an authenticated session from a cloud service to a broker’s MT5 server) feel like filling in a form. That meant:

The goal was zero support tickets for “I can’t connect my account.” The broker connection step is the biggest abandonment risk in the funnel, and it’s entirely solvable with good copy and real-time validation.


Metrics

Onboarding
< 5 min
From registration to active portfolio.
Accounts per user
Up to 3
Different brokers, one dashboard.
Execution isolation
Per-container
One agent per user, no shared state.

Lessons learned

What we’d do differently (and what we’d do the same)
  • Isolation-first architecture pays for itself. The operational complexity of per-user containers is worth it — shared state in trading systems creates cascading failure modes that are very hard to debug.
  • Scope the permissions at the API level, not the application layer. “We only request trading access” is more trustworthy than “we never call withdrawal endpoints in our code.” The former is verifiable.
  • Event stream aggregation is not optional for trading UIs. Raw tick streams overwhelm browsers and create misleading volatility in the UI. Meaningful state snapshots improve UX and reduce client-side bugs.
  • Onboarding UX at the broker connection step determines conversion more than any other factor. Invest engineering time here — real-time validation and plain-language errors eliminate most support volume.
  • MT5 reconnection logic is harder than it looks. Exponential backoff with jitter, broker-side maintenance window awareness, and session health checks are all required for reliable cloud integration.

Ready to build production AI systems?

We help teams ship AI that works in the real world. Let's discuss your project.

Related posts

Related reading