meh, if you don't have kids, $125K is plenty to live in a so so part of sunnyvale or mountain view (which is totally safe, just your apartment will be built in the '60s to working class standards, which isn't as bad as it sounds; the weather here means that having flimsy and poorly-insulated housing isn't as big of a deal as it would be otherwise.)
I mean, you won't be buying right now, but you will be able to save money; if we have another big drop in housing prices, you will be all set: otherwise, you will just have to move when you retire. (which actually is pretty sad, 'cause those social connections are really important. but just saying, if you have $125K/yr, two people can live here comfortably.)
If it's really important that you have a lot of room, you aren't going to like it here. Really, I think that's the big difference.
My own impression is that as a sysadmin without a degree, I get like 2x here what i would other places, and yeah, housing is more than 2x, but... housing is a kinda small part of my budget. I save a lot more working here, and have access to a lot more luxuries that don't involve personal space.
Honestly, if you wanted to get me to move? Probably the best thing you could promise me is a job with an office... or even just the sort of large cubicle my job role rated in the mid to late aughts. I mean, my job pays really well, the food is good and people are nice to me, and I really appreciate it, but it seems like every year my desk shrinks. I think the parking spot they reserve for the car I don't use is allocated more space than the desk where I sit all day.
Most adults do have kids, though. It's unreasonable to expect that one will not have kids, seeing how we're all here because our parents were in a position to have kids. So I chose to live elsewhere instead.
I support your ability to choose but so much of the commentary here is to the effect of “nobody should live in CA, living in CA is impossible, nobody wants to live in CA in fact everybody is leaving!” I’ve even seen a post say it’s negligent to consider raising kids in CA or the Bay Area. We’ve lived in the Bay Area 18 years, we have a kid and a house and save money, it took us 15 years to get to this point, if you want to just show up and have it all then maybe choose slewhere but crapping in living in CA or the Bay Area is getting tired
Out-of-the-box, it's only really designed to scale to a certain point. It's all generally nice, predictable, and with with low latency up until that point. But because the nodes are fully meshed, the TCP heartbeats alone kill performance once you go past that point. So for ex. 100 nodes gives you 5050 TCP connections (100+99+98+97...etc). As parent says, there are methods to deal with this (Riak Core would be an example). But they're non-trivial.
+ you possibly need to bear in mind the design goals: that Erlang is designed to run as a highly reliable, self contained system in _a single geographic location_, with that system possibly left to run on its own for long periods of time (years)
So, at one level, 5000 tcp connections is a lot, but at another level, some teams (including mine) are running hundreds of thousands of tcp connections to our clients from our front end Erlang nodes.
I've never thought about the dist heartbeats as a scalaing problem. If you have thousands of dist nodes, and your nodes have small memory, dist buffers for each connection to add up -- I think the default is 8mb, you can tune it, but it's a scaling concern. Especially, if you have nodes far apart from each other.
Really, the root design of Erlang was for two nodes colocated in a single chassis. That said, it turns out the design scales pretty well to much larger numbers of nodes, and nodes farther apart, but you have to be careful with some things. pg2:join and leave operate under a global lock, which will be slow if you have contention on the lock, or if one of your nodes has some problem where it's still up but very slow. Mnesia doesn't do well with queuing without a lot of help, schema operations under queuing is definitely a bad idea as well.
If you want to run Erlang at larger scales, you will need to be ready to poke around in OTP, and ocassionaly in BEAM as well. If you're running big systems, IMHO it makes the most sense for your Erlang nodes to fill your physical nodes, so I don't see much need for containers, but if you do use containers, you need to figure out how to get their names consistent for Erlang, or it's going to be confused. (OTP has a concept of a 'diskless' node which would seem to be a good fit for an ephemeral systems environment, but I must admit I haven't played with that)
> If you want to run Erlang at larger scales, you will need to be ready to poke around in OTP, and ocassionaly in BEAM as well.
That's essentially what I've had to do in my career as an Erlang engineer. Erlang requires way more massaging and work than the stories people tell about it would lead you to believe.
I don't think it's that much work. It's just that when you hit a wall, you have to fix it yourself. But many of the fixes are easy -- OTP usually does things in a very simple way, and sometimes something more complex is needed to scale beyond.
I think this is the case regardless of what languages or systems you use, but more well used systems may have more experts and more documentation to lean on.
For things that are a good fit for Erlang, it seems worth it to train up a couple people with deep internal knowledge of the VM you're using. As you said in another part of the thread, Erlang doesn't have a lot of abstraction -- most scaling problems aren't too many layers deep.
Yep, I kinda meant it as an illustration - the heartbeats are just the base operation that has to occur between meshed nodes, not that that itself is generally going to be the issue (the inter-node communication is likely to have a bit more going on than just that!).
Containers is where I've had issues, not necessarily anything drastic, but I've found myself dropping half of the the things I really want from an Erlang system (mainly making as much as possible non-stateful rather than stateful, not using supervision trees to their full potential) to buttress against that ephemeral nature of containers (I haven't really looked at diskless nodes in much detail either though)
I can't really go into it in detail, but at a high level Erlang default methods of distribution and security don't scale very well. There are people working on better mechanisms for this, and I know of several companies that have custom solutions for clustering nodes. One big issue is you cannot easily burst Erlang nodes to handle peak traffic. The number of nodes is usually relatively static in a deployment.
Bursting is an interesting thought. I think, if you planned it out, it could be done -- subject to some constraints.
It would be hard to burst stateful (mnesia) nodes --- schema operations require a lock across all the nodes in the schema, and that lock requires that the nodes not be in the middle of the 'log dumping' process (where the global transaction log gets divided into per table logs and such), which means long delays in high volume situations, and even longer delays if doing multiple schema operations. This could probably be patched around, but... In my team's experience, our mnesia nodes were generally ok under higher than normal load, expansion was driven by data size. Expansion could be a lot nicer, but I haven't heard of many database systems that handle expansion off the shelf.
So that leaves stateless nodes. I don't see why you couldn't burst those, especially if using standard dist. Bring up the host, push your software, connect to one dist node, and get meshed automatically, once you see all the pg2 groups you need to operate, enable traffic.
That said, we never did too much of that, we're in bare metal hosting so we don't have an incentive to run different server counts at different times of day, and provisioning isn't fast enough to handle incidental spikes -- we have a pretty good model of what spikes to expect, and provision to handle that load being mindful of the possibility of a load spike during a network or datacenter availability incident.
Our nodes are stateful. We also wrote our own dist (I didn't write it, it could be a lot better). We also have good metrics on our spikes, we just have black friday where we need to burst like crazy.
Oh yeah, black Friday is crazy. For us, we've always been seeing that our annual big spike load ends up being our sustained daily peak in a few months, so we will need those nodes anyway.
Dependencies have cost. You have to monitor for updates, notify the maintainer(s) of any bugs, keep an eye out for security vulnerabilities, and sometimes (gasp) even step through them with a debugger.
Doing that for one dependency is bad enough, but for 100s it's a nightmare.
Personally, I prefer to just pull the pieces I need out of an open source library (unless it's very well maintained, or huge). It's like doing a code review at the same time, so you're aware of what's going on in your application.
Copy/pasting has a nearly identical cost (aside from notifying the maintainer), except you have to catch all of them, you removed an easy upgrade path when other people catch the issues and you're spending vastly more time "code reviewing" every dependency you have rather than actually producing the software you're trying to write.
Don't know about you, but we have actual goals and I'd never meet them if I tried your method.
I think he might be talking about trivial dependencies, like leftpad, classNames, arrify, etc. In the case of trivial dependencies, rolling your 30-line "util.js" file to remove 3 dependencies is definitely worth it. No one is suggesting you roll your own diffing algorithm.
I think I already responded to you elsewhere, but in case I'm incorrect: No it is not worth it. You are re-inventing the wheel so you can pat yourself on the back. Nobody hires a software engineer to write leftpad. Rolling your own diffing algorithm is exactly what actual engineering entails.
Not quite, that would imply time and effort. I'm talking about reinventing the toothpick (2-3 lines of code), which is much different than reinventing a complex library for the sake of reinventing it.
> Rolling your own diffing algorithm is exactly what actual engineering entails
That's nice, but you're addressing a straw man. No one actually said rolling your own diffing algorithm is not what engineering entails. It was said that no one is suggesting you recreate a non-trivial dependency for the sake of reducing your dependency count.
I can use it in an example if it helps: If you are hired to write a basic website and you choose React, then you probably shouldn't reinvent React as your first step in writing the website. React is a fine dependency because it does a lot.
Humor me -- the next time you use classNames for a small project, try and see if you can't replace all of your calls to classNames with very basic template strings or other trivial code. It should not take any effort. For example I've seen things similar to "classNames({myClass: true})" in code before. Can you see what is wrong with this line? When people get comfortable with abstractions, they completely forget how to write the simplest code.
> Not quite, that would imply time and effort. I'm talking about reinventing the toothpick (2-3 lines of code), which is much different than reinventing a complex library for the sake of reinventing it.
Re-inventing 1000 versions of a tooth pick is reinventing the wheel.
> That's nice, but you're addressing a straw man.
You keep using that term and I'm not sure you understand what it means.
> It was said that no one is suggesting you recreate a non-trivial dependency for the sake of reducing your dependency count.
And my argument is that dependency count is one of the dumbest metrics to be interested in. Size, sure as that impacts bundle size, which in-turn, effects latency. But "count" is meaningless.
> Humor me -- the next time you use classNames for a small project
I use styled-components exclusively for React projects now.
> For example I've seen things similar to "classNames({myClass: true})" in code before.
So? Bad code is bad, that's not a library failure. Now that is a straw man.
> Can you see what is wrong with this line?
Of course I can, because I'm actually good at my job. I also wouldn't do that. Using your toaster in a bathtub is also REALLY stupid, but that doesn't mean we should ban toasters.
> When people get comfortable with abstractions, they completely forget how to write the simplest code.
No that's called laziness and it has nothing to do with dependencies. You have twice in this thread accused me of straw men inaccurately, and now wrote a paragraph dedicated to a huge straw man.
> Personally, I prefer to just pull the pieces I need out of an open source library (unless it's very well maintained, or huge). It's like doing a code review at the same time, so you're aware of what's going on in your application.
To quote yourself:
Doing that for one dependency is bad enough, but for 100s it's a nightmare.
'Forking' a project's dependencies (which is effectively what this is...) is often fraught with as much trouble as just having the damn dependency in the first place.
3 Different things. html, css & js are like raw materials, React is processing these raw materials, and a UI components or design systems are the result you get if you mix the React process with manual labor.
The're frameworks and design systems. A React UI framework refines or enhances the React process to build UI components or design systems.
Bootstrap e.g. is 2 things in 1, it's a process/framework and design system that sits directly on top of html, css & js.
Sounds like you can get away with a bash script that calls rsync, and restarts the code on the server with ssh. (I deploy one of my websites this way, simple & reliable)
If you're looking for something more legit:
Ansible
The largest reason is cost. My small deployment (3 nodes) is running around $100 / mo on AWS (That's my app, nginx, redis, and postgres).
It doesn't even need 3 nodes, I don't recall if 3 is the minimum, but realistically I only need one (for now). For larger projects this is probably a non-issue.
Second largest reason, is that really I have no idea what is going on on these nodes, and I probably never will. Magically my services run when I have the correct configurations. Not to say that's always a bad thing, but I've found it difficult to determine the default level of security as a result of this.
A third reason is the learning curve. This is less of an issue because I've invested the time to learn already. But like, the first time I tried to get traffic ingressed was painful.
As to what I'm moving to, I migrated one of my websites to a simple rsync + docker-compose setup and am pretty happy with it. In the past, I ran ansible on a 50 node cluster and it worked really well.
I'm not really clear on how moving off Kubernetes saves you money in this scenario. Seems like the most likely source of the cost is the AWS, which is the non-free part. I'm just learning k8s, so I feel you on the learning curve.
Kubernetes has a minimum node count.
Moving to one node, saves cost, by a factor of 3. Not to mention all of the other resources it creates (load balancers).