Emilyjones

Emilyjones

Could OTP handle the latency demands of a crypto order matching engine?

Been thinking about this after seeing a few concurrency and distributed-systems threads pop up here lately. Curious what the more systems-minded folks in this community think.

An order matching engine is the part of a crypto exchange that pairs buy and sell orders and decides who trades with whom, all in real time, under serious load. The two things that matter most are correctness and latency. You need every order processed in the right sequence, with zero room for race conditions, while still handling tens of thousands of orders per second without falling behind.

On paper, that sounds like exactly the kind of problem OTP was built for. Model the order book as a GenServer or a set of processes per trading pair, lean on message passing instead of shared mutable state, and you get a natural way to serialize order processing without hand-rolled locking. The BEAM’s preemptive scheduling also means one heavy computation on the matching side shouldn’t be able to stall the whole system the way it might in a single-threaded event loop.

Where I’m less sure is whether the GC pauses or process messaging overhead become a real bottleneck once you’re chasing the microsecond-level latency that serious matching engines aim for. Most production write-ups I’ve come across take a more traditional low-level approach for the actual matching logic. There’s a decent technical breakdown of how a matching engine is typically architected here if anyone wants the non-Elixir baseline to compare against: order matching engine in crypto exchange development.

Has anyone here actually built or benchmarked something matching-engine-adjacent in Elixir, even a toy version? Would love to know where it started to strain, whether that was GC, messaging overhead, or something else entirely.

First Post!

ausimian

ausimian

You will have to measure on your intended hardware. You should consider that 1-3micros is probably best-in-class for pure ‘software’ based trading engines (tick-to-order), or at least was when I worked in this space, admittedly over 6 years ago now.

This relies on full ethernet kernel offload to userspace, and then fast (e.g. c++ with typically little allocation / arena allocation) single-threaded engines running in a hot loop, pinned to a physical core and the kernel told to ignore that core for scheduling purposes. There are a number of things here that make it unlikely that you’ll compete successfully with engines like these, before you even get into GC, cache-unfriendly data structures (pointer chasing), branch mis-prediction etc.

That said, if you can successfully trade via a strategy that is not so latency focused then I think the beam would make a pretty great starting point. GC is per-process and generally constrained. Process isolation gives you some reliability guarantees.

I would probably run each instance of a strategy (e.g. per instrument ) in its own process. If you have multiple strategies trading the same instrument, you may need some way to amortize their orders, if you’re not allowed to cross yourself in the markets you trade.

Importantly, I would have your data feeds (e.g. order-book) update ETS tables and then just ‘ping’ your strategy to wake up and re-evaluate the data inside them. Sending market data as messages into the mailbox of your strategy risks you trading on out-of-date information.

As background, I was working on FPGA based trading engines over a decade ago where latencies were around 250ns from memory, some of this was simply bounded by how quickly you could clock in bits off the wire, make a decision and start clocking bits out. I believe we may even have had a version that started clocking bits out before the full packet had been ingested, with ip-checksum poisoning used to ‘abandon’ the packet if there was no good order to be sent. Fun times.

Where Next?

Popular in Discussions Top

WildYorkies
It seems that the more I read, the more I find Elixir users speaking about all the ways that Elixir is not good for x, y, and z use cases...
New
lucaong
Hello Elixir and Nerves community, I have been working for a while on an open-source embedded key-value database for Elixir, that I call...
230 14049 124
New
lorenzo
Hey everone! I created a prototype for my app using Nodejs for the api. But the framework I chose wasnt great (in general theresnt any g...
New
nburkley
AWS re:Invent is on at the moment with some interesting announcements. One new feature in particular is the Lambda Runtime API for AWS La...
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New
sergio
There’s a new TIOBE index report that came out that shows Elixir is still not in the top 50 used languages. It also goes on to call Elix...
New
boundedvariable
I am going through the kafka architecture. All the features what the kafka is providing are already in Erlang. I would like hear your opi...
New
scouten
I’m looking for a host for the server part of a small (personal) side project that I’m working on. It’s currently written in Node.js and ...
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New
AstonJ
It’s been a while since we’ve had a thread like this, so what better way to kick off the year with :003: What does being an Elixir user ...
New

Other popular topics Top

hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a > b) do {:ok, "a"} end if (a < b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 43806 214
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New

We're in Beta

About us Mission Statement