Hacker News new | ask | show | jobs
by ThePhysicist 1468 days ago
I started my first Rust project a month ago after working for years in Golang and before that Python (and before that Perl, C/C++ and Turbo Pascal). I really like the whole experience but I'm not sure if I'd recommend writing all your backend code in Rust as a startup.

Rust definitely provides a pleasant experience and is very powerful. If you can stick to the standard library I think Rust is great, though the package ecosystem is still lacking in many respects and most packages seem immature and quite limited. So if you plan to build something that has sizeable external dependencies plan some time to either write that yourself or to spend a lot of time debugging and vetting external packages, many of which are maintained as side projects by single developers. Documentation often also seems to be subpar as compared to e.g. Python. I suppose that's due to the auto-generation of documentation which seems to lead to people mostly writing what I'd refer to as API documentation with very few tutorials.

So is Rust worth it for a startup? Not so sure. I recently picked up Python again to write a simple REST API, and the process is just so much faster and (for me) enjoyable because of the "ad hocness" of the language and of course the great existing tooling around it (I still have to find an ORM as powerful as SQLAlchemy in Rust or Golang). And let's be honest it's also possible to write great scalable services in Python (or Ruby, or Javascript), as many scaleups still use these technologies.

Onboarding of developers might be another issue: Yeah, everyone wants to be a Rust programmer, but for people that have little experience with systems programming the learning curve is quite steep, so you'll limit your candidate pool quite a bit and will need more time for hiring.

6 comments

Two things I consider:

1. what languages does the team already know best?

2. are any languages dominant in the problem space?

for us, I've used Python over 10 years and Python is the leader in data science / analytics. Some things might be a little faster if we used Rust, but compute is cheap. Go with what you know.

>compute is cheap. Go with what you know.

sorry for picking on your comment in this generic fashion but I am critical of these memes not your observations:

Compute Is Cheap(where Gustafson Bariss is true)

https://en.m.wikipedia.org/wiki/Gustafson%27s_law

Going with what you already know is fine for knocking out the cobwebs and getting into a space. But most generally certainly in my experience I've never done anything to completion I knew at the beginning.

My response to the "compute is cheap" argument is always: Discord powers millions of concurrent live-chat and real-time-voice users from literally single (huge) VMs, using Elixir and Rust. Their revenue (relatively) sucks; its a powerhouse in communication because their revenue sucks (zero barrier to entry); and because their revenue sucks, they were forced to actually think critically about the technologies they use. They can't just throw more computers at the problem; and that limitation produced a far better product than, say, Slack.

Ok, smaller scale. You look at the latest Show HN SaaS product and wonder: "Why is there no free tier?" Free tiers are a classic in SaaS; it gets customers in the door, using your product, and you can upsell to higher tiers. Its all the same backend no matter the cost; but if your infrastructure & engineering costs are high, you may not be able to afford a generous free tier.

The days of the SaaS unicorn are behind us. Also; the days of Moore's Law (server-side at least) are quickly dwindling. This idea of "just throw more compute at the problem" needs to die a painful death. This week I consulted with a startup with something like $500k in ARR, spending $80k/year in cloud infrastructure. No free tier, all enterprise contracts, the most basic CRUD app you can imagine. A hundred NodeJS containers, every security service AWS offers enabled and logging terabytes of useless shit to an S3 bucket, autoscaling their database up to 100s of gigabytes in memory because "we don't have time to optimize". Sure; you also don't have time to not to. You're banking on some large enterprise contract to come through and buy another year; which will also add a few tens of thousands of more users to the platform, so you'll tweak the scale numbers up again, and again, and just keep praying one day you can cost optimize. Every day that goes by makes that harder, so you're also praying that maybe you can find more talent to do it, maybe we can grab some people from these layoffs, except what if we don't have the money to pay for talent just like the company that laid them off?

Python, JS, Big Cloud, had their time and were valuable during it; but today, startups need to think about cost optimization from day 1, and every cycle a CPU spends doing something is a cost. I'm not prescribing technologies; I'm just asking for more critical thinking, and not always operating with the "throw money at it" mindset. Maybe python makes sense; how can we deliver it with extremely low costs? Lambda? DigitalOcean? Can we integrate a more performance-oriented view into reviews? This part of the app experiences 10x the traffic the rest does; can we break that out into something far more efficient?

[1] https://discord.com/category/engineering

I agree that one doesn't necessarily need a fast language, but I think that the "hardware is cheap" idea is very misleading. Renting/owning 5x as much servers may be cheap, but maintaining them isn't.
check out https://cloud.google.com/run. I've never had issues 5x-ing compute on it.

All the other services that compute hits (e.g. Postgres) are a different story, but that doesn't really matter when picking a language.

1 may be better asked as what aspects of your team understanding of any considered language apply to your problem space. How well can you port that knowledge to another model of expression.

2 is fine. the more significant question is often do you want to work with that talent pool and does the pool tell you more about the costs structure of your sector against which information you may prefer to tack against the prevailing winds and even more patiently attempt to trade actual equity for deep abilities and stuff what language is chosen if your stock has value.

I don't understand how much attention individual languages receive. Plural understanding across your team and ability to transcribe the code into valid parseable docs against which APIs are easily written, is paramount in my mind. Corollary to my incredulity I have often thought that you emphasize the codebase language and dialects only to find you fuelled holy wars and dissipated your technical mission values. Which is disastrous for hiring the kind of colleagues we get up in the morning and forget about industry grief to share increasingly awful spaces with.

> I recently picked up Python again to write a simple REST API, and the process is just so much faster

For me it's much more important how will it work in the next few years, not how quickly you can write it. If I could, I would use Rust for pretty much everything just because I don't like getting paged in the middle of the night.

I have both Python and Golang web services in production for years, none of them cause much headache. I'm not running a hyperscale startup though and server hosting is the smallest cost factor for running my products, so I don't worry about performance that much. Most workloads are IO-bound (database queries) in any case, so Python isn't too much at a disadvantage over Golang or Rust there. In terms of stability I never had any major issue with Python services, and when minor issues occured the logging and tracebacks were so good that it was easy to isolate and fix the problem (the same is also true for Golang).

I guess the older you become the less you care about specific tools or languages, for me it's mostly the general architecture and operating principles of the software that determines if a system will be brittle or not.

> … how will it work in the next few years…

If we were talking about code, wouldn't that look a lot like premature optimization?

Build one, throw it away…

I agree. This typing velocity argument is really weak. It may be faster to start, but talk to me once the project reaches 10K+ lines of code and we'll see how you fare with your scripting language.
>Yeah, everyone wants to be a Rust programmer

I understand why you might have got that impression, but that's a far cry from the reality

It really puzzles me why smart people want to spend their time satisfying the borrow checker rather than inventing new and useful things.
I don't remember the 'satisfying the borrow checker' phase lasting more than a few weeks. Once you internalize the rules the borrow checker gets out of your way and it's more of a sanity check.

I think part of the issue is that it wasn't very well explained in the book at the time I started learning rust. This might have improved since.

The entire way of coding in Rust revolves around satisfying the borrow checker. At some point it may become second nature, but you are still jumping through Rust's hoops, which will make your code full of compromises that would otherwise not exist.
>you are still jumping through Rust's hoops, which will make your code full of compromises that would otherwise not exist.

The same can be said in reverse. There are many, many C and C++ codebases that make design compromises and copy data unnecessarily so as not to be utterly hellish to maintain. People meme about "fearless concurrency" but it's true, with Rust you don't need KGB levels of paranoia and attentiveness to write parallel or reference-heavy code. I can write code in Rust I would never be comfortable writing in C/C++ because the language gives me the confidence to not compromise in those areas.

So does the entire way of coding in any static-typed language, your code is full of compromises that would otherwise not exist in a dynamic-type language. Rust is just another layer of static typing.
Yes. It's another level of the same problem.

Rust is like a piano where certain keys have been removed so you never play out of key.

"It really puzzles me why smart people want to spend their time satisfying the (compiler errors | warnings | linter) rather than inventing new and useful things."

Over the past fifty years we've realized that even incredibly smart people suck at avoiding the gazillion pitfalls involved in programming. Virtually every professional programming environment these days employs a suite of tools that help ensure we don't make certain classes of avoidable mistakes, and the borrow checker is simply another one of these tools to protect us from ourselves.

Am I to assume you don't turn on any warnings or linters in any of your projects?

Sometimes I think that people get bored programming so they need languages to make it harder and interesting lol
Just an exaggeration of course based on the current hype and over-enthusiasm for the language.
I wouldn't touch Python with 10-foot pole for any serious project. People who're used to dynamic languages (e.g., JavaScript) are now starting to see how indispensable static typing is when they try out TypeScript and then never want to go back.
I also write Python with type annotations and the type checker keeps getting better and better, though I find it's often not strictly necessary, at least for small projects. The most important thing is to keep the code simple to understand and follow, then you can write great software in dynamically typed languages as well.

Also have Typescript experience but in general I'm not a big fan of gradually typed programming languages, static typing works best in languages that were designed for it from the ground up and that offer an expressive type system, e.g. C++ or Rust.

Deno could be a good alternative. It should hit GA 3 QT this year.
I would not choose Deno for that considering how little there is for it currently and how much of what there is available that is plastered with all caps warnings to not use it in production.
I would like to add that async Rust still doesn't really work. That is a big negative for Rust.
I've been using async Rust in production for years. The learning curve is a little higher than I'd like. But it works great and it does everything we need it to. For an open source example, see https://www.dbcrossbar.org/

Many problems with async Rust involve people trying to get overly clever with lifetimes and zero-copy code. And if it's not either of those, it's people getting overly clever with async traits. So keep it simple!

Some tips:

1. Long-running async tasks should own their data, not borrow it. This will save you 80% of the pain right there.

2. Don't be afraid to allocate futures on the heap, and use "Box<dyn Future<Output=T>>" to hide the implementation.

3. If you must use traits with async members, use "async_trait".

4. Remember that futures can be cancelled at any "await" point. You can ignore this 99% of the time, as long as you use destructors to perform cleanup.

I would only recommend async Rust if you actually need very high-performance async code. Regular threaded Rust still works great for most things, as do languages like TypeScript. But if you actually need what async Rust offers, it's totally workable.

This constant refrain must be discouraging to the people who have worked so hard on async rust. Can we please restrict our criticism to specific problems, and temper it with gratitude for the amazing things that the Rust developers have already given us free of charge?
I am not sure what is so "un-tempered" in the original message (assuming it is not technically incorrect) and what makes Rust so special that criticism must be "tempered with gratitude".
It's too vague. The claim is that async "still doesn't really work" but like, how so?

Sometimes you could make a claim like that about a feature and it's more or less accurate just as it stands. C++ 20 Modules were like that (still might be like that?) on most platforms, 'cos it turns out that's a lot of work for a compiler to implement and it's important to say you have the feature even if you know it doesn't work well. But even then, I'd rather see e.g. "C++ 20 Modules blow up if I try to A, or B, or C... or Z" it's just that I can understand if your list is a page long "doesn't really work" seems more concise than listing everything.

There are clearly people who are frustrated by aspects of Rust's async. Some of those frustrations are fixable, some are consequences of a principle decision that's unlikely to be revisited, and who knows if you won't say what frustrated you

Suppose I said Go's generics "don't really work". Do I mean that they aren't monomorphised in the way I hoped? That the syntax is too untidy for me? That the Go libraries aren't yet making them ergonomic? That I found a compiler bug? No way to know.

I understand and agree with what you say. It is ""tempered with gratitude" part of the original message I do not grok.
Well, I have several production services. They are written in async rust. If they didn't work, or worked poorly, or even worked sorta good - you'd know it, the outages would be front page news in the tech press and maybe even on "the news".

I didn't have to do anything special to make them work well, just out of the box tokio and a small bit of learning how to do stuff that's weird to do in most any language (e.g. netlink, bpf maps and so on).

I don't know what the definition of "doesn't really work" is, but it seems technically incorrect given how my services run for months at a time between restarts (which I consider a symptom of working).

Rust isn't special; what I said applies to any open-source project. But people have been pretty harsh about async in Rust lately, and IMO the message I was replying to makes the problem sound worse than it is.
Lol. just replace Rust with C++/Java. Does your opinion change ? Because no one cares about being gentle to C++/Java in the HN community.
It definitely works just fine
My main issue with Rust async was that it wasn't possible to write a "runtime agnostic" libraries. For example, I wrote an HTTP client with Tokio and later wanted to use it in a project that was using another runtime (I think it was async-std) and couldn't use it. I wonder if that has changed since then?
That's basically only a problem if you use async-std (just don't, and switch your project if you have). Pretty much everything supports tokio (or there is a just-as-good equivalent library that supports tokio).

Which isn't to say this shouldn't be fixed. Just that there's a fairly good away to avoid the problem in practice.

This is probably more of a concern for people who aren't writing services/ professional devs. Otherwise, who cares, you pick a runtime (tokio) and you use it - runtime agnosticism isn't a real goal for any company.
You can find great examples of Rust async programming being "a disaster and a mess". You still can consider it is working just fine, but I disagree.
I don't really need to find those examples, I've written most of my company's product in Rust using async, for years, and it's never once been an issue. That's 100s of thousands of lines of rust written and 0 async issues.
Totally valid, but you could also say the same thing about C and C++, i.e. you can wield your tool with mastery, then that's awesome. But I think the average startup would likely struggle needlessly when they really just need to ship products that people want/need to use. Rust is likely not the smartest choice for the average startup.
Only one person at the company had previous professional experience with Rust. The majority had 0 experience with it at all. We've had no trouble and it's actually been our most productive language - we're moving away from Python and Typescript where possible.