Ask
271
@quietpackets ·

Rewriting a Python ingest service, Go or Rust when nobody on the team has shipped either?

Three backend developers, all comfortable in Python and nothing else. The service takes roughly 3k JSON messages a second off a broker, validates them and writes batches to Postgres, and it currently needs four boxes to keep up. We have about six weeks before a traffic event that will roughly double that, and our ops team already deploys other people's Go binaries so that side is solved either way. I am not asking which language is better, I am asking which one a team like mine survives shipping in six weeks.

9 answers Share
Report

Answering anonymously — a moderator will review it first.

  • @parquet_pile · 2mo ago

    I have ported the same class of service to both, about a year apart, so I can compare rather than speculate. The Go version took a fortnight for a first working cut and was in production in a month, and the code was boring in the way you want infrastructure to be boring. The Rust version was faster in the end and used noticeably less memory under load, but the first working cut took over a month, and most of that was not the borrow checker, it was choosing between ecosystem options for every single dependency and then discovering they disagreed about async.

    If the workload were CPU bound number crunching I would say Rust and mean it. For pulling messages off a queue and shovelling them at a database, Go's standard library and one database driver gets you there and the performance difference will not be the thing that decides your event.

    176
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @dark_room_dev · 2mo ago

    Go. Your ops team already runs Go binaries, which means deployment, observability and on call are solved on day one. That is worth more than any benchmark you will read this week.

    109
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @edge_runtime_bo · 2mo ago · 3 replies

    Go, on the deadline alone. A competent Python developer is writing useful Go within a couple of days and reviewing it usefully within two weeks. Rust is a genuinely better language for several things you might care about later, and it is also a month of your six being spent learning when to clone and which async runtime you are in. Six weeks with a hard external date is not the project you learn a hard language on.

    217
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
    • @flakey_test · 2mo ago

      There is usually one of those on every team and they are usually right about the language and wrong about the timing.

      88
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
    • @quietpackets · 2mo ago

      That matches my instinct, I just wanted to hear it from people who have been through it rather than from the person who wants to write Rust.

      34
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
  • @chmod_confused · 2mo ago · 2 replies

    Mild disagreement with the framing rather than the conclusion. Everyone says Go for the deadline, which is right, but the reason people regret it eighteen months later is usually error handling discipline and unbounded concurrency rather than performance. If you go this route, decide on day one how errors get wrapped and where you cap concurrency, because a worker pool that spawns per message will happily take your database down at 3k a second. Get those two conventions written down before anyone opens an editor and the six week version stays maintainable.

    138
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
    • @edge_runtime_bo · 2mo ago

      Strong agree on capping concurrency. The most common Go performance incident I have seen is not slow code, it is a goroutine per item hammering a connection pool sized for twenty.

      62
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
  • @two_vcpu_club · 2mo ago

    Before you pick a language, work out where the four boxes are going. Ingest and write to Postgres is an I/O shaped workload, and if your Python is spending its time waiting on the network and the database, a rewrite in anything compiled buys you far less than you expect. Profile it for an afternoon first.

    In my case the honest answer turned out to be that we were spending most of our CPU in JSON deserialisation and in building one INSERT per row. Swapping the JSON library and moving to batched writes cut our box count enough that the rewrite got deferred by a year. If yours is genuinely CPU bound in parsing then Go will help a lot and Rust would help slightly more, but find out which world you are in before you spend six weeks.

    194
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @napgapnora · 2mo ago

    We picked Rust for a service like this with a team who had not written it before. We shipped four months after the six week estimate. Almost none of that was the borrow checker, which people warn you about and which you get used to. It was the long tail: picking an async runtime and finding a library that wanted a different one, compile times slowing the feedback loop to a crawl on a big workspace, and code review taking twice as long because two of us could not confidently review the third's code. The service has run beautifully ever since and I would still not choose that timeline again.

    124
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report