I will also push back on other commentors here saying Rust is not good for web apps and APIs, and I have found that to be the opposite of true. I read Zero To Production In Rust [0] (a great book by the way, all about creating a web API with actix-web and Postgres) and deployed an API that has not gone down a single time since deploying near the beginning of this year. It's as ergonomic as (and sometimes even more so than) any NodeJS or Go API I've made (as even though Rust doesn't have function overloading, actix-web and others have some macro magic they do behind the scenes to make it appear as if it does), and there were very few times I had to contend with the borrow checker. If there had been and if I were really going for speed, I would also have cloned everywhere that was needed.
When I write something in Rust and it compiles, I can depend on it to work, and to continue working. At the end of the day, use the tool that makes sense for your business, but I don't think Rust was necessarily a bad choice based on my personal experience with it.
I actually think that, ironically, the if err problem with go is worse for reading code than writing code. If you are used to the pattern it's not that difficult to add the `if err != nil` after a fallible function call, and as is mentioned elsewhere, linters can help catch if you miss it. However, if you are trying to figure out what a function is doing, it can be very difficult to follow the flow, when 3/4 of the code is
if err != null {
return err
}
especially if you don't have a lot of experience reading go code. And that 3/4 is not an exaggeration. I have had to read functions where literally every line of normal logic is followed by those three lines to propagate the error from the other function. A function that would otherwise fit on a single screen now takes up over three screens worth of scrolling.> God I get tired of the generics criticism with Go. I truthfully don't even notice it when I write Go, I don't understand why folks get so bent out of shape over it.
Over ten years later, Go gets generics.
I actually like Go over Rust, but really, really wish the language provided some more ergonomics and fixed several of its terrible gotchas. (the for loop issue for example)
Also wish Go gets RAII some day.
I don’t think that’s any better in Rust though.
After going through the book, I've found that I simply use the same boilerplate for every new project, so it's more of a `write-once, use again` type of deal. In that case, I don't worry about the time it took to get to the point where I could do that reusing.
I’ve worked my way through a couple of rust books, but this was the first one that actually talked not just about the language, but the entire development flow. Git workflows, CI/CD, docker, comprehensive testing.
Even after clearing the initial rust fundamentals, there are so many standard libraries like anyhow, chrono, serde, thiserror, and tokio that are almost required knowledge, but aren’t covered in most books.
Thank you for sharing your discovery!
Not that this takes away from your point, but does Go have function overloading? I had assumed it hadn't given the discussions I had heard about what it would take to retrofit `Context` parameters on everything when they added that type, but I guess maybe this could be one of those "functions can but methods can't" things (which I think I heard is how they do generics as well?)
That's going to get tiresome after about half a day.
Exceptions or GTFO.
Result<> or Go returning many values is wayyyy better.
There's also a bit of annoying typing stuff involved, but generally with something like the anyhow crate you can handwave that away too.
In fact, you can often return Result from an underlying function from your own, achieving an effect similar to exceptions.
Personally, I actually think it's a worse fit for things like kernel/embedded development than for web backends. The ergonomics of Rust are so Javascript-y that the web is natural, and other environments where C is used are a lot messier and trickier.
However, it didn't have much support after TypeScript took the JS world by storm. If it had, we might have seen the same great Rust-like benefits on the frontend as well, and perhaps the backend too instead of NodeJS.
There were just a couple of failures in the first 2 months.
How often does the codebase change? How many people work on it?
Its dumb when the C++ community refuses rust when it guarantees memory safety, so why would you bring in a language you prefer to an area that doesn't need it if it introduces that issue?
If you like Result<> or concurrency, use a GC language with those things. Go may not have them, but your choice isn't just Go.
IMHO C# is also an excellent choice, but there's a lot going on behind the covers to keep it working properly in a multi-threaded web environment. This mostly doesn't concern you as a developer, until it bites you.
This is really the main reason not to use Rust when you need to move fast: if you don't know the language yet, it will take you time to learn it. But that's true of any language. You probably shouldn't do your startup in Java, either, if your team isn't familiar with it.
Yes, Rust's learning curve is steeper than many other languages, but still... if you're an early-stage startup and you need to move fast, write in a language that you and your team already knows.
Java is wildly easier to pick up than Rust, though. Hordes of productive enterprise java programmers are employed today who frankly don't even understand what memory safety even means, much less the tradeoffs their language runtime (or software) needs to make to ensure it.
It's certainly a truism that you should tailor your development environment to the talents of your staff, but that doesn't mean that all tools are equally applicable. Would you do a startup today using APL or COBOL?
I think Java is a little easier to pick up than Rust, but not much. And this is especially true if one is not already familiar with Object Oriented programming. Classes are weird - conflating a number of concepts that really ought to be orthogonal to each other (and I remember thinking so as a beginner, although I couldn't articulate why then). IMO, structs, enums, and traits are much easier to explain to a beginner.
Rust does have the overhead of needing to care about ownership and memory, but I don't think that's as significant as you might think (and Java also leaks some of these details in for example the difference between objects and primitive types), and it partially makes up for it in other areas.
As an experienced Rust dev, I had the opposite problem. I looked for a good Rust job, but couldn't find one. Took an Elixir job instead.
I also don't get the complaint about lack of productivity. I've worked in a dozen languages, and Rust is still the most productive language for me by far. I feel like they're speaking from inexperience here. I'm slow whenever I start a new language too, and Rust was no exception. Keep at it, however, and it'll pay off in the long run.
Did you work on it with a team in a serious production environment?
Sounds like you struggled to find a Rust job, so I'm not sure how you can know that without really betting on it like these guys did.
I did. I left because management was a brood of compulsive liars.
I think this should be at the top of the post. Rust seems like an obvious bad choice for this. For something not performance-sensitive that doesn't require most of Rust's power just use languages/frameworks that are made for this kind of thing. Of course you can do this with Rust, but you're probably picking the wrong tool for the job. The Rust ecosystem around building typical webservices isn't nearly as good as it is for other languages, and the benefit you get from Rust's safety and performance is worth less than the iteration speed you gain from the standard Node/Python/etc approach.
A CRUD/SaaS web team should only be using it for high performance areas with a few microservices. At least until the web side of Rust significantly matures (mostly in the people/community side not just code).
But I've used Rust mostly for performance-critical CLI tools, or highly specialized servers. Typically, these have a narrowly defined job that must be done reliably and efficiently. Rust shines at this. These tools run reliably with almost no changes, often for years at a time.
But I have learned that it's often less useful putting policy and frequently-changed business logic in Rust. That kind of code is often accessible to more developers in a strongly-typed scripting language.
I assume that you’re thinking of TypeScript or Python with type hints.
Do you mean that these languages are more accessible because they are more widely known by developers or because codebases in these languages are easier for some reason to change frequently than codebases in Rust?
One of the tradeoffs of programming in Rust is that you need to distinguish between value vs. reference, stack vs. heap, and a number of other choices like that. This helps performance tremendously. But unless most of your team is comfortable making these decisions, they add a modest tax to all Rust code written. At least compared to TypeScript.
Rust is a fantastically productive language now that I know it well. There's definitely a point on the learning curve where Rust can be competitive with several popular scripting languages. But getting an entire team of programmers to that point takes a concerted effort.
So for many teams, Rust is the biggest win for problems like:
- "I need a server that handles a few kinds of specialized requests at high speed."
- "I need a CLI tool that can process 60 GB of input data on a regular basis."
- "I need to parse this file format that involves 197 special cases that I must keep carefully straight."
I just haven't found it to be the case that developers have a very hard time learning it, but we haven't grown to the point where that would maybe be the case. We also lean heavily into microservices so "oh there's no library in Rust but there's one in Python" is low cost, we can just write a service in Python.
By contrast, using Rust makes it easy to force a readable coding style on yourself and others.
You know what Rust looks like to me? Perl without the dollar signs. There's your write-only language, you just have it backwards.
But the article pretty clearly outlined a super simple CRUD app. These days that's a problem space so well defined you can practically specify the whole thing in command line flags. Rust really has little to add there. For other stuff, yeah Rust can be super cool.
Can you expand on this, please?
Whenever I work on the Python service I feel like I'm working in clay. Like, everything kind of sort of works. It won't at first, but then you just poke at it with a stick until it does. In Rust, it works or you're told exactly why it doesn't and then you fix it.
I change a struct and the compiler provides me with a list of places that need updating.
I have many reasons (mypy, type system, testing, venv, python 2), but really the big one is rust's superior type system as well as general tooling (lsp is way better, cargo and clippy are phenomenal).
On a big project, you are going to be reading a lot more code than you are going to be writing.
It's remarkable how significantly the first few months of a project impact the first few years of a company. How quickly casual & spontaneous decisions, largely based on convenience and familiarity, ossify into legacy drag.
- C/C++ developers like it as an alternative for low level languages
- Functional programmers like it because of it's functional features
- "Cargo Culters" / "Hot Language" / "Flavor of the Month" followers like it, as it's in vogue at the moment (this is the crowd that has likely shifted from various web/API scripting languages over the last decade - (php|ruby|python) -> nodejs -> rust)
However, as the article alludes to, for the third crowd, Rust is just likely not a great fit (even if it has a lot of neat features and introduces some great concepts others may not stumble on of their own accord) when your implementation doesn't do much beyond web dev/API/scripting purposes.
While Rust isn't simple, I don't know any other languages that fill this space.
With a competent teacher, experienced devs should be able to pick up on the memory model pretty quickly, and that is really the only initial blocker to productivity. After that a dev can essentially write procedural code if they want, like other common languages, while refining their thinking and practices towards idiomatic Rust.
Well, that's because linked lists are not simple. The linked blogpost makes that clear enough.
1. I'm familiar with lifetimes and they don't slow me down anymore. Also, I usually structure my projects such that I don't need to explicitly express them.
2. I spend a lot less time fixing bugs because Rust makes them impossible.
The wasted clock cycles and developer hours more than makes up for the slow down in productivity rates we’ve seen across advanced economies lately!
Just like how SQL gives you a faster way to not only store and search through binary trees but also to write the instructions to do so means that we should be able to do the same for web applications.
I’m not sure that most parts of a web application need to be Turing complete. User permissions? Data validation? Can’t we have GUI tools with a 1:1 mapping to more declarative code, ala SwiftUI? Why are we using a garbage collector for an HTTP request when we could just be freeing up memory after the response is sent?
Ur/Web: http://impredicative.com/ur/
Dark (Darklang): https://darklang.com/
Second, when you wire up a web server module with a SQLite module with a JSON module and translate between them in Ruby or Python you’re taking a really big performance hit. Just think about how many times something is being translated into an unused intermediate state because that just happens to be how the ready-made pipes are sized.
I’m saying, let’s build a bunch of ready-made pipes that are built specifically for SQL backed HTTP servers and with the features that we all seem to use on every project.
The end result should make it easier and faster to build a more performant web application.
But here's something to really chew on. Do we need the HTTP server at all?
Consider: why exactly do we need so much middleware plumbing for ordinary database driven web apps? A lot of this is to do with a winding evolutionary path rather than what you'd design with a clean slate.
Something I've been experimenting with lately is writing apps that connect directly to an RDBMS using its native protocol, over the internet, from a desktop app. Obvs the next step after is to try the same with a mobile app. Historically we've relied on web browsers and written translation layers for a few different reasons, but tech has been improving over time and some of those reasons are becoming obsolete:
1. Free relational databases were really rough back then and the commercial DBs often had weird limitations around distributing DB drivers. These days it's easier and postgres is a lot better.
2. You needed to slather lots of caches and other stuff in front of the RDBMS if you had high traffic. Modern DBs are a lot better at materialized views, cached query plans, read replicas etc. Postgres has a variety of load balancers that can sit in front of it and work around its per-connection overhead.
3. Security wasn't good enough. Nowadays you have features like row level security, security-definer views etc in the free DBs.
4. People translate everything to HTML/HTTP partly because it was too hard to distribute and update apps to Windows desktops/laptops in the 2000s, due to MS just generally losing the ability to execute and being distracted by stuff like Longhorn/WinFS. Browsers solved the basics of caching and refreshing of code for you. Now there's https://conveyor.hydraulic.dev/ which makes distributing desktop apps way easier. It's a lot more feasible now to just knock out a quick desktop app and upload to an S3 bucket, with built in online updates. Also the next release will support force-update-on-start, so you can get a web like experience where the user is always up to date so the schemas and client can be evolved in parallel.
If you could just write your UI using a 'real' UI toolkit and invoke directly to the DB from the UI code, you wouldn't need a lot of the microservices plumbing anymore, you wouldn't need to serialize stuff to JSON or HTML. You could just use the underlying DB protocol as an RPC layer and let the DB enforce business logic. It can be done for common kinds of enterprise apps today: there are only a few problems to solve, none of them especially hard. For instance a little service that turned OAuth SSO into client side certificates would make it easy to connect to a DB without needing to manage usernames or passwords. A tunnelling solution to get through awkward firewalls would also be useful (websockets etc).
For consumer apps there's more complexity. You wouldn't try to implement twitter that way for instance. But still, for the kind of SaaS-y thing that the article is about it could have saved a lot of complexity and improved iteration speed.
Funny enough, another thread introduced me to Truffle and I came across this article of yours!
> This project was a cloud-based SaaS product that is, more-or-less, a conventional CRUD app: it is a set of microservices that provide a REST and gRPC API endpoint in front of a database, as well as some other back-end microservices
Of course.
Use Java/Kotlin or Node.js/Typescript or Go or Python for your basic web services.
Easy test: Would you at least seriously consider using C/C++ for it? Only then should you use Rust.
I'm a Rust-stan for sure, but I probably wouldn't use it for this task either as it'll be hard to find other people who know how to use it - and also for this task. Here's hoping that changes, though.
[edit] I might also add it's not a good fit for making these types of endpoints at a startup as the goal of a startup isn't really to write perfect/correct/safe code, but rather to ship a product as fast as you can so you can iterate on the product-market fit. Quick and dirty in another language is probably a better fit for the business case. Rewrite it later.
1. The risk of future unsafety (a GC language will always safer than rust)
2. Faster development that's easier to change on a dime.
3. No risk of memory leaks (which can happen in safe rust)
This is a great point. I understand liking a language, but don't bring Rust into a GC space (in industry, personal projects can be what you like!) You can find a GC language with all the features of rust you like.
Ruby on Rails certainly isn't perfect, but it's a highly battle-tested web framework. It's been so widely used for so long that you can have high confidence that you won't run into any bugs that will require digging into the guts of it. You can write code against it and be highly confident that any bugs or misbehaviors are in your code, with difficulty of finding and fixing dependent only on how good the code you've written is.
With Rust, I don't think that's the case. The DB and web server related libs just don't seem to have that much manpower behind them, and haven't had big complex services built on them in production for years. If you want to do anything mildly complex, there's a good chance you'll have to dig into the guts of these to figure out what's really happening or to resolve some weird bug or add a feature. That'll require a lot of skill, even if the code you're actually writing is mostly straightforward.
If you've ever generated some object out of some factory and then tossed it on a list of things and then gone back to generate a new object out of the factory and found that the first object you put on the list got scribbled over because you forgot to clone it, then that's a category of bugs that rust entirely prevents.
And I thought I was pretty good about reasoning about data ownership in other languages, but the borrow checker is teaching me how to be a lot more careful.
I have been doing compiler development in C++ for about 10 years, lisp before that and a bit of python more recently.
We could not figure out how to be productive in Rust after starting a greenfield project and sticking to it for a month.
Luckily this was not a project which requires incremental updates, we were on the verge of rewriting it in C++.
It took me almost a year to be as productive (and my code as canonical) in Rust as I was after over two decades of C++.
After a month of Rust I was still fighting the borrow checker and grokking basic concepts of the language. So no surprise in what you wrote.
However, after that year I am probably a factor of two to ten more productive in Rust.
The speedup is about two for everyday code (if it compiles it runs and doesn't crash). Ten (or more) when I need to bring in a dependency.
To qualify the latter: if a crate with same functionality or a Rust wrapper for a C/C++ lib exists, the factor can be much, much higher than ten since it is just adding a line to Cargo.toml.
If the dependency is a C/C++ lib it is as slow as using it from C++. It needs to be integrated with the build and that takes about the same time plus writing/generating a wrapper.
All that said: I had to write code in C++ the other day again. It almost felt painful after three years of only Rust.
It's one line of change for any build system..
Why?
Those ecosystems are built alongside C++ tooling, so no need to add an extra layer of indirection.
I already have the safety from those ecosytems, if I am reaching out to C++ is exactly because I need to do some unsafe stuff, or binding libraries that are anyway written in C++.
This is not a criticism of Rust, just a trait which needs to be acknowledged if the situation has to be improved.
I'm not sure if I agree with this. In fact, I'm pretty sure that I don't. These "occasional" nuisances become big blockers after a while and not only decrease productivity but hurt customer goodwill as well when they're not discovered in time.
I feel that it is actually harder to write bad code in Rust than it is in say, Python.
If you're really a startup, looking for a product-market fit, then you don't know exactly what you're building yet. There's a high change you're going to throw away a lot of code.
e.g. you spend effort caring about scalability, flexibility, proper architecture, full test coverage — only to hand it to users who will say they won't buy it, it's not actually the feature they wanted. You can learn such lessons with crappy copy-pasted code, and then worry about code quality once you've figured out what to actually build.
At the expense of safety.
So "there's a huge bifurcation between people who know this language and people who don't" is a good reason to pick another language. As with so many such techs, network effect can dominate other benefits.
Yeah, the infamous tin soldier approach that's often used to excuse using worse but more entrenched languages.
Rust or not, there's an argument to be made for statically typed languages improving productivity over the long run [0].
All development can feel sluggish depending on the work hours, estimates, business timelines, engineering skills, and the task at hand.
Programming languages are common targets because - we use them so much - there are so many - and all developers, at some point, must choose to dedicate their time to one over the others.
Finally, productivity itself is only one performance characteristic. To focus only on that (without even a good definition of effect or measure) makes content precisely what the author claims to avoid; flame bait.
[0] - https://www.researchgate.net/publication/338162224_A_Study_o...
Especially that is has first-class support for gRPC, runs on every cloud/on-prem host you can think of and doesn't force you to go out of your way to get most performance out of your implementation. People should not be mentioning Java first as a GC/JIT-based language for cloud given how competitive C# stack is and how much more you get straight out of the box.
I haven't used it in years, but I didn't find the anywhere near as full an ecosystem around C#, it's tooling, it's libraries, etc. It didn't help that there was a lot of confusion around what ran on which runtimes/versions.
Perhaps it's changed since then.
About 2 weeks in, I hit a blocker, where the most performance critical layer was running 30x slower than C#. It's two weeks since then, and I'm still blocked. Experienced programmers on the language Discord and Reddit have been stumped as well, and I get the impression this is what one should expect from an immature ecosystem, but also makes me fear that it will never actually catch on.
Point is, I think even the selling point of speed is inappropriate.
As for Rust’s performance, it has been proven time and again to approach that of C and C++. One counterexample does not disprove that.
In a single threaded version, it beats C#, though not by as much as I would have expected. The essence is that I have to run the same calculation on a large array of doubles that spits out another array of doubles, so I parallelize it with SIMD and threads. In C# I max out at AVX-2 for instruction level parallelism, but for Rust, I use AVX-512, and it's not even 2x faster, though it is faster--it should be more than 2x faster because AVX-512 has better instructions to work with. But when I combine this with doing the calculation in threaded parallel chunks on the array, it goes far slower than it should.
I'd argue C++ is not anywhere easier, if you are using its features or need to analyze the code that does. It won't be anywhere quick.
> I don’t know about anyone else, but at least for me, when I’m building a new feature I usually don’t have all the data types, APIs, and other fine details worked out up front. I’m often just farting out code trying to get some basic idea working and checking whether my assumptions about how things should work are more-or-less correct. Doing this in, say, Python is extremely easy, because you can play fast and loose with things like typing and not worry if certain code paths are broken while you rough out your idea. You can go back later and make it all tidy and fix all the type errors and write all the tests.
> In Rust, this kind of “draft coding” is very difficult, because the compiler can and will complain about every goddamn thing that does not pass type and lifetime checking — as it is explicitly designed to do. This makes perfect sense when you need to build your final, production-ready implementation, but absolutely sucks when you’re trying to cruft something together to test an idea or get a basic foundation in place. The unimplemented! macro is helpful to a point, but still requires that everything typechecks up and down the stack before you can even compile.
This rings so true for me. I could "mock up" entire apps using interfaces in Java, without having to actually write impl code. I could be sloppy as hell around the edges, but that didn't matter, because I could get the large design right without the compiler screaming.
In Rust, there is the chasm between no code and anything that works, feels so draggy.
> Over time, we grew the team considerably (increasing the engineering headcount by nearly 10x), and the size and complexity of the codebase grew considerably as well.
At this point, Rust is providing security and protection from technical debt. You have lots of new comers to the company/project and each one of them is adding or changing something. Developers being normal human beings have the tendency not to read documentation, old code or discuss with 100 engineers before building something.
Rust forces that on them, to a certain degree. Sure, you can move faster without Rust for now; but you'll pay the price later on. I am working on a company where we are doing microservices both in Rust and TypeScript. It's faster to get the job done in TypeScript; however, the cost is the maintenance later. The TS microservices breaks easily, regress much faster when someone modifies them, and are prone to invisible bugs. Rust is more solid in that front.
But in a world where speed of delivery and delivery itself (just deliver and deal with it later), Rust will definitively not shine. This is kicking the problem down to somebody else.
Another point: Because of that, Rust libraries are usually pretty solid. Comparing to the untangled mess in NPM, Rust will break down much less frequently.
Rust forces that on them, to a certain degree. Sure, you can move faster without Rust for now; but you'll pay the price later on
If you're lucky enough to be paying any price later in a startup then your business is living.The last thing on my mind when commercializing something is future technical debt.
The flip side argument for an early stage company is that if they can’t move fast they may not survive. Not having tech debt is great, but it’s better to have tech debt and be alive than no tech debt and out of business.
To be clear, I’m not personally taking a hardline position on either side here. I think these kinds of choices are always a balancing act. Moving too fast can kill your business just as effectively as moving too slow: it’s just as hard to ship changes to a permanently on fire ball of spaghetti as it is a pristinely typed piece of clockwork, and sometimes harder.
True for most startups.
Editor/IDE should be able to do this in a few seconds.
Those three things are actually just different facets of the same thing: ownership. The bad news is that you must learn Rust's ownership model to use Rust idiomatically. The good news is that you can do a lot without learning Rust ownership model at all. Just clone all your values. Not advisable for production code, but great for getting over the ownership model hump.
Context matters a lot, and you shouldn't be making tech choices based on the way the wind is blowing ("tech radars", what's hot in the blogosphere, etc.). If hiring teams to work on your mostly-CRUD app easily is a high priority, then Rust probably isn't a good choice. If you have a team that already knows Rust, and you need to add some web app / service, then Rust is a perfectly fine choice, on the grounds that support for web stuff is "good enough" now, and the best tool for the job is often the one you already know well and are already supporting.
If I'm building stuff for _myself_ and it's getting too fiddly for a bash script, then I'll always default to Rust just because _personally_ I'm way more productive in it than anything else.
Context, context, context.
If your alternative is Python or Ruby, then cloning your values is perfectly OK for production code. It will still run very fast.
I would love to hear what tech stack (or stacks) the HN community thinks currently allows a small team to move fastest for this type of product.
I guess nodejs might also be throw into the party, as it is anyway needed for many SPA frameworks, and for better or worse, Go, given its relevance on DevOps space.
Second tier, a bit higher performance, yet somewhat less productive: ASP.NET Core; Spring Boot; Node/Express/Nest; maybe Go
- Laravel
- Rails
- Next.Js or similar
- Python
- C#/Kotlin/Go
Add login and auth and stuff via ory/keycloak
Great point
Part of this depends on one's bar for quality. In Node.js I could write `JSON.parse(input).foo.bar` really quickly. In Rust, I'd probably write two struct definitions with `#[serde(Deserialize)]` first, then a similar line. It'd take 45 seconds longer, but when I'm done, the Rust program validates the input and prints decent error messages.
I like that this is enforced in Rust (and that many other things are well beyond what tsc guarantees), and I like it in Node too and I’m glad that a certain corner of the ecosystem takes it seriously.
If you were in typescript, zod would also automatically generate your interfaces too.
Does it match the experience of a team and its need to collaboratively deliver software quality across varying levels of engineer experience? If not, then I'm not sure your individual experience is pertinent to the subject matter at hand (using Rust at a startup).
If you don't need performance, you might be better off using any number of safe, GC languages. (That said, I actually find the ergonomics of Rust nicer than most other languages. A rust-like language with a GC would be very nice for web backends imo.)
This is a problem in general, but it's not a good reason to use Rust in a startup, it's a good reason to use Java or C# or TypeScript or another well-worn high-level language with static typing.
Rust's niche is solving a set of security problems that most high-level languages don't have. Choosing it for a startup only really improves your security if the other language you're considering is C or C++.
Then you talk about why "startups need regulation" and the lack thereof is why "the world remains an insecure mess" which is another non sequitur drawn from statements which, while individually correct, would never combine to imply that conclusion.
The world is an insecure mess because some societies have not collectively agreed that it is more expensive to be insecure than secure.
Startups don't "need" regulation anymore than regulation is a cure for any problem. In practice, poorly drafted regulation exacerbates rather than solves the problem it is scoped to solve because it opens the door for regulatory capture based monopolies.
That said, I do agree with parts of many of your individual statements: more effective regulations would be good not just for citizens but for startups and society in general; memory safety oriented code tends to be higher ROI for everyone; the world remaining an insecure mess is a pox on global societies whereupon well deployed investment into secure infrastructure would produced significant ROI compared to the present state of the world.
that seems a little alarmist, don't you think?
This could be true for C++, Java or maybe C#. Against them, python/ruby run circles.
But Rust change the equation.
Is super-productive... BUT what is important to note is that you need developers that have done the initial climb and go fully rust with it.
After this, things start to click neatly:
- Modeling code is easy & fast
- Composing code, flow!
- Testing (all of it, including benchmarking and integration) flow.
- Refactoring (big!) is super-easy. This one is where the "velocity" is actually need.
But you CAN'T "code fast". You CAN'T skip in good practiques "let's ignore the use of clippy, Result, proper use of traits (like Into/From), etc". (and even write documentation with including doc-test!)
This is where the "I write code FAASSST bro!, not time for pesky good practiques!" get hurt with Rust.
You need to buy the whole package, because Rust is MADE to be used fully in harmony.
And when you finally do it. IS FAST TO CODE.
And even FASTER to refactor.
And probably so minimal post-fixes.
---
P.D: Major blow against Rust? Slow compiling. This is the one factor that blow the dream and where you truly need a decent machine and flow to make it nice. However, if you take the above advice, you are already with Test/DocTest/Clippy/Check flow and that part can be done to be efficient.
I really dislike python in production and have done it a lot more than I've ever wanted.
Are you actually a C++ programmer? I work at a firm that uses C++ and Rust and this isn't the case at all. Setting up dependencies, tests and benchmarks is a one-off cost, most C++ compiler errors are quite understandable to experienced devs unless they're doing something really hairy, and C++ has algebraic datatypes, as a library (std::variant) via variadic templates, something Rust doesn't support. For C++ devs comfortable with template metaprogramming Rust is missing a bunch of features, many things that are relatively simple in C++ are literally impossible in Rust (at least without writing macros). Rust also doesn't save much on debug time if writing single-threaded code, because memory errors are a very small proportion of the bugs one encounters in modern C++ written by experienced devs, rather most bugs are logic errors, which Rust doesn't prevent.
If you're willing to blindly follow the suggestions given you by the compiler about references, and clone() things when it doesn't seem to work, you'll be just as productive as a Python/Java ... programmer. You'll just not be as memory efficient as a Rust programmer who actually groks that stuff. That's the tradeoff: coder productivity versus memory efficiency.
I feel like 90% of my struggles with Rust in the real world have to do with the borrow checker. The two pieces don't feel related enough to me that they need to be interlinked.
This sounds just like all other projects that don't keep the code professional.
The author complains a lot about the quality of the Rust libraries and documentation, but I bet that their code base and documentation and especially testing is worse.
Still, I agree that Rust is not ready for a startup where the requirements change often.
Naturally, there is a reason people opt for higher level languages like Ruby/Python or at least Go or Java/Kotlin to write apps like this.
I understand why Rust is trying to shove its way into the CRUD/web space--that's where all the programming is. I just don't understand the converse.
Not all languages are as bad as Python, and Rust comes with a lot of other costs. But it's very seductive to think about a world where you build a static binary with a single command, the build always works no matter what system it's on, the binary always works on the target OS regardless of what else is or isn't installed, it will use 1/10 the memory, and most likely it will never have any runtime errors because you were made to handle them all already
(I realize Go has at least some of these benefits, but its type system is hard for me to stomach)
Can you elaborate on the issues of Go's type system?
A note on performance, Rust's the only langauge where I haven't had the need to update my unit test harnesses to `TRUNCATE` tables instead of creating/discarding a separate database per test on PostgresSQL.
I'll also like to mention the gem that is SQLx[1]. As someone who's never been satisfied with ORMs, type checked SQL queries that auto-populate your custom types is revolutionary. With the error-prone langauge-SQL boundary covered, I was surprised just how good it can get making use of the builtin PostgreSQL features. Almost to the point that amount of effort the community's put to building great tools like Prisma.js and <insert favorite ORM> feel like a fool's errand (at least so for PosgreSQL).
[0]: https://github.com/alexpusch/rust-magic-function-params
[1]: https://github.com/juhaku/utoipa
[3]: lib.rs/crates/sqlx
And, well, the usual, "learning curve" and some largely hypothetical concerns about hiring. I developed a complex app with Rust with very high time pressure and with developers that didn't have any previous Rust experience (I didn't have much of it myself), it was risky but it worked out well, so I know first hand that it's possible. And we are not "ex-google"!
(Not /s, I genuinely think it's cool things are like this now)
- Rust tends to push you to make good decisions. In my case, one of these good decisions was to ditch an ORM (which has always slowed me down) and instead write Postgres queries directly via SQLx. The compile time checks against an actual DB helped my speed dramatically
- Free performance can be a really big help when you are trying to figure out an API or algorithm. It's really helpful to know that my unoptimized code won't tank the server, and also helps me save costs on the cloud.
- "It doesn't compile, or it doesn't break" is kinda a mantra for Rust, and really helps me focus on problems at hand, instead of hunting down bugs.
> You will have a hard time hiring Rust developers.
I've found that there is a drastic difference between hiring devs willing to learn Rust, and devs that want to work with you because you are using Rust. The bar of those devs that seek out a Rust position tends to be very high.
> We made a huge mistake early on by adopting Actix as the web framework for our service...(To be fair, this was a few years ago and maybe things have improved by now.)
Actix-web has gone through some version-churn, but it's never been "buggy" in my experience. The experience multiple years ago is vastly different than today, but even my older services written years ago with Actix-web are still running fine.
> Libraries and documentation are immature.
Perhaps in years past, but I've always found the docs for Rust and its libraries to be very good. Folks write entire books on elements of Rust, and the standardization of the display of crate docs keeps things consistent.
> Rust makes roughing out new features very hard.
The "json!" macro can come in handy here. Also Github Copilot is a godsend for this.
> What really bites is when you need to change the type signature of a load-bearing interface and find yourself spending hours changing every place where the type is used only to see if your initial stab at something is feasible. And then redoing all of that work when you realize you need to change it again.
Hours? These type of corrections are spoonfed to you via errors at compile, or via the IDE. I've never had to spend hours on this. Everyone of these changes could be a bug, and having a typesafe language is a huge help here.
I recognize I might be in the minority, but I've really enjoyed using Rust for services for my startup. It's helped me move fast, but maybe I'm a special case. I'm curious to hear other's experiences.
I often reach for Rust when Python could do, but it’s a bit bigger than a one page of code program. I also forget I’ve been doing Rust nearly full time since late 2015. And before that 15 years of C and understanding memory, etc. Maybe we’re just a rare breed.
You should be using the language you know best or dynamic languages when you are trying to move fast.
Jokes aside. This is a thoughtful and interesting article. I was wavering on going down the Rust path for my SaaS start-up. Glad I didn't in the end for exactly the same kind of reasons.
The goal is to deliver products and iterate as fast as possible. Productivity is key to success.
IF (and it is a big IF) your startup ever gets to the point of having to scale up (nice problem to have) then just throw money at AWS, hire senior engineers and let them figured it out.
What matters is customer experience; nobody cares of what’s behind the scene.