Connecting MetaTrader 5 to Your Own Backend: 4 Architectures Compared

Home Blog Connecting MetaTrader 5 to Your Own Backend: 4 Architectures Compared

Sooner or later every serious MetaTrader project hits the same wall: the logic you need doesn't fit inside one Expert Advisor. You want a risk engine that sees all accounts, a dashboard, a database, signals coming from your own models, or a copy-trading service. That means MetaTrader 5 has to talk to your own backend. There are four realistic ways to do that, and they differ enormously in latency, robustness and operating cost.

This article compares them the way we do in client projects: what each option is good at, where it breaks, and which one we would pick for which situation.

The four options at a glance

Aspect 1. WebRequest (HTTP) 2. Native sockets 3. DLL bridge 4. Python package
Direction Terminal pulls (request/response) Bidirectional, persistent Bidirectional, anything you build External process drives the terminal
Latency One HTTP round trip per call, plus polling interval Low: one open connection, push possible Lowest: native code in the terminal process Low locally, but one process per terminal
Complexity Low Medium (framing, reconnects) High (native code, memory safety) Low to medium
Restrictions EAs and scripts only, URL whitelist, blocking call EAs and scripts only, host whitelist "Allow DLL imports" required, not on MQL5 VPS or Market Windows only, terminal must run on same machine
Best for Low-frequency reporting, config, licensing Signals, copy trading, central risk Heavy computation, existing native libraries Research, data extraction, simple automation

1. WebRequest: HTTP from inside the EA

MQL5 has a built-in WebRequest() function. Your Expert Advisor sends an HTTP(S) request to your API and gets a response back. It's the simplest option and it uses tooling every backend developer knows: a REST endpoint, JSON, normal TLS.

string url = "https://api.example.com/v1/positions";
char   body[], result[];
string headers = "Content-Type: application/json\r\n", resultHeaders;
StringToCharArray(payload, body, 0, StringLen(payload));
int status = WebRequest("POST", url, headers, 5000, body, result, resultHeaders);
if(status != 200) Print("Sync failed: ", status, " err=", GetLastError());

The catches:

  • It's a blocking call. While the request is in flight, your EA's event handler is stuck. A slow API means a slow EA. Never call it from OnTick() on every tick; batch and send from a timer.
  • It's pull-only. The terminal must ask; your backend can't push. To receive instructions you poll, which adds the polling interval to your latency and creates a lot of empty requests.
  • Whitelisting. The URL must be added under Tools → Options → Expert Advisors → Allow WebRequest for listed URL on every terminal. That's fine for your own infrastructure and painful for a product you distribute to hundreds of traders.
  • Not available in indicators, only in Expert Advisors and scripts.

Use it for: account reporting every few seconds, fetching configuration, license checks, end-of-day exports. Avoid it for: anything where a delay of a second or a stalled EA costs money.

2. Native sockets: a persistent connection

MQL5 also ships TCP socket functions (SocketCreate, SocketConnect, SocketSend, SocketRead, plus SocketTlsHandshake for TLS). The EA opens one connection to your server and keeps it open. Now your backend can push a message the moment something happens, without the terminal having to ask.

This is the architecture we use most for copy trading, signal distribution and central risk monitoring. It gives near-real-time behaviour without leaving the official, sandboxed MQL5 environment.

What you have to build yourself, because a raw TCP stream gives you none of it:

  • Message framing. TCP is a byte stream, not messages. Use a length prefix or newline-delimited JSON and handle partial reads.
  • Heartbeats and reconnects. Connections die silently (VPS restarts, NAT timeouts). Send a heartbeat every few seconds from both sides and reconnect with backoff.
  • Non-blocking reads. Check SocketIsReadable() from OnTimer() so the EA never waits on the network.
  • A protocol with message IDs. More on that below, because it matters for every option.

Sockets have the same restriction as WebRequest: Expert Advisors and scripts only, and the server address must be in the terminal's allowed list.

3. DLL bridge: native code inside the terminal

MQL5 can call functions in a Windows DLL through #import. That DLL can be written in C++, C# (via an unmanaged export) or Rust (with a C ABI), and inside it you can do anything: run a ZeroMQ or gRPC client, use shared memory, call existing quant libraries, or run computations that would be painfully slow in MQL5.

This is the most powerful option and the riskiest:

  • The DLL runs inside the terminal process. A crash, a deadlock or a memory leak in your DLL takes MetaTrader down with it. This is a strong argument for writing the bridge in a memory-safe language like Rust and keeping it small.
  • Users must enable Allow DLL imports. Products using DLLs can't be sold on the MQL5 Market, and DLL calls are not allowed on MetaQuotes' own virtual hosting, so you need your own Windows VPS.
  • You're now shipping and versioning native binaries (32/64-bit, runtime dependencies, antivirus false positives).

Use it when you need computation or connectivity MQL5 can't offer, or you're integrating an existing native library. Our MetaTrader library development work is mostly this pattern: a thin, well-tested native core with a simple MQL5 interface on top.

4. The official Python package: drive the terminal from outside

MetaQuotes publishes a MetaTrader5 Python package. A Python process on the same Windows machine connects to a running terminal and can read rates and ticks, query positions and send orders (initialize(), copy_rates_from(), order_send() and so on). No EA is needed.

It's excellent for research, data extraction into your own database, and simple automation driven by a model you already have in Python. Its limits show up at scale: it's Windows-only, each Python process talks to one terminal, and there's no event push, so you poll. Running dozens of accounts means dozens of terminals and processes to supervise.

A note for brokers: the Manager and Server APIs

Everything above is terminal-side: it works with any account at any broker. If you are the broker, MetaQuotes licenses server-side interfaces (the Manager API, plus Server and Gateway APIs) that operate on the trading server itself: all accounts, all deals, real-time events. That's a different architecture altogether and the right one for back-office, risk and CRM integrations at broker level. See broker technology consulting if that's your situation.

The part that matters more than the transport

Whichever option you choose, most production incidents we see come from the protocol rather than the pipe:

  1. Make every instruction idempotent. Give each order intent a unique ID and store it in the order comment or magic number. When a message is retried after a reconnect, the EA can recognise "I already did this" instead of opening a second position.
  2. The terminal is the source of truth for execution. Your backend sends intents; the EA reports what actually happened (fills, partial fills, rejections, requotes). Don't let the backend assume an order exists because it asked for one.
  3. Reconcile on every reconnect. After a disconnect, the EA sends a full snapshot of positions and pending orders, and the backend corrects its state from that.
  4. Normalise time. Trade server time is not UTC and differs per broker. Convert at the edge and store UTC everywhere else.
  5. Fail safe. Decide explicitly what the EA does when the backend is unreachable: keep managing open positions with local rules, stop opening new ones, or close everything. Don't leave it to chance.

What we would pick

  • Reporting, dashboards, licensing: WebRequest from a timer. Simple and good enough.
  • Copy trading, signal distribution, central risk across accounts: native sockets with a small, well-defined message protocol.
  • Heavy computation or an existing C++/Rust library: a DLL bridge, kept as small as possible, on your own VPS.
  • Research and data pipelines: the Python package, feeding your own database.

Many real systems combine two: sockets for the hot path and HTTP for everything else. If you're designing one, our trading system architecture review is a good place to pressure-test the choice before you build. See also MetaTrader 5 development and MetaTrader integration.