Live data from Hacker News

In Defense of Simple Architectures (2022)

danluu.com

401–410 of 447 posts

Re: In Defense of Simple Architectures (2022)

#401
post #19

Earlier quoted context omitted.

Yep. Microservices! AWS! Everything Gartner and Thoughtworks says! It'll look good on my resume... ..several years later.. Escalating cloud costs, high staffing cost, staff turnover, heavily reduced margins, decreased productivity, burnout, clients unsatisfied, C-suite paving over this by hiring more marketers...

I wonder how many early stage businesses went tits up because they drank the microservice kool-aid and burned valuable engineering cycles that should have been spent on features on docker spaghetti.

I once interviewed at Fast. One of the questions they asked was how to scale up a rate limiter. In my mind I was wondering why you'd ever need to worry about scaling up a rate limiter. The answer apparently was some kind of microservice.

The company eventually folded[1]. Turns out the company was burning millions of dollars in hiring + infra, while generating only $600,000 in revenue.

[1] https://newsletter.pragmaticengineer.com/p/the-scoop-fast

Re: In Defense of Simple Architectures (2022)

#402

I agree with the general sentiment that simple architectures are better and monoliths are mostly fine. But. I've dealt with way too many teams whose shit is falling over due to synchronous IO even at laughably low volumes. Don't do that if you can avoid it. "Subtle data-integrity bugs" are not something we should be discussing in a system of financial record. Avoiding them should have been designed in from the start.

> shit is falling over due to synchronous IO even at laughably low volumes. Like? I ask because even synchronous IO let's you serve millions of requests per month on a cheap VPS. That's enough in the b2b space to keep a company of 1000 employees in business.

I had a similar thought when C# introduced async/await. "Why all this complexity? What was wrong with good old fashioned blocking calls?"

I don't know the answer, but I would like to. I think it has to do with the limit on the number of processes/threads that the OS/framework can manage. Once you reach this limit, using async/await somehow allows the OS/framework to secretly use your (technically not) blocked threads to do some other work while they are (technically not) blocked.

Re: In Defense of Simple Architectures (2022)

#403
post #236

Earlier quoted context omitted.

It's much easier to make smaller scope changes at higher frequency than it is to make large changes at lower frequency. This is the entire reason the software industry adopted CI/CD

I'm not sure that's measuring what you think. The CI pipeline is an incentive for a good test suite, and with a good test suite the frequency and scope of changes matters a lot less. CI/CD is also an incentive to keep domain-level scope changes small (scope creep tends to be a problem in software development) in order to minimize disruptions to the pipeline. These are all somewhat different problems than upgrading th…

CI/CD is usually a component of DevOps, and any decent DevOps team will have DORA metrics. Time-to-fix, frequency of deploys are both core metrics, and mirror frequency and scope of changes. You want change often, and small.

Yes, change failure rate is also measured, and that's why good test suites matter, but if you think frequency and scope of change don't matter for successful projects, you haven't looked at the data.

That means frequently updating your dependencies against a small code base is much more useful (and painless) than occasional boil-the-ocean updates.

(As always, excepting small-ish teams, because direct communication paths to everybody on the team can mitigate a lot of problems that are painful at scale)

Re: In Defense of Simple Architectures (2022)

#404

Earlier quoted context omitted.

> Services, or even microservices, are more of a strategy to allow teams to scale than services or products to scale. I've never really understood why you couldn't just break up your monolith into modules. So like if there's a "payments" section, why isn't that API stabilized? I think all the potential pitfalls (coupling, no commitment to compatibility) are there for monoliths and microservices, the difference is in…

> I've never really understood why you couldn't just break up your monolith into modules You can! We used to do this! Some of us still do this! It is, however, much more difficult. Not difficult technically, but difficult because it requires discipline. The organisations I’ve worked at that have achieved this always had some form of dictator who could enforce the separation. Look at the work done by John Lakos (and v…

> It is, however, much more difficult. Not difficult technically, but difficult because it requires discipline.

Before that, people need to know it's even an option.

Years ago when I showed a dev who had just switched teams how to do this with a feature they were partway through implementing (their original version had it threading through the rest of the codebase) it was like one of those "mind blown" images. He had never even considered this as a possibility before.

Re: In Defense of Simple Architectures (2022)

#405

Earlier quoted context omitted.

> shit is falling over due to synchronous IO even at laughably low volumes. Like? I ask because even synchronous IO let's you serve millions of requests per month on a cheap VPS. That's enough in the b2b space to keep a company of 1000 employees in business.

I had a similar thought when C# introduced async/await. "Why all this complexity? What was wrong with good old fashioned blocking calls?" I don't know the answer, but I would like to. I think it has to do with the limit on the number of processes/threads that the OS/framework can manage. Once you reach this limit, using async/await somehow allows the OS/framework to secretly use your (technically not) blocked threads…

1. Async allows you to parallelise tasks. If a request from a user needs to hit three logically independent endpoints, you don't need to do that in sequence, you can do them in parallel and thus the user will get a response much quicker.

2. OS threads can be expensive in the sense that they can block a lot of memory, to the point where you could run out of threads at some point. This is worse in some environments than in others. Apart from async, another solution for this is virtual / green threads (as in Erlang, Haskell, and much more recently, Java).

3. Some async implementations enable advanced structured concurrency patterns, such as cancellation, backpressure handling, etc.

Re: In Defense of Simple Architectures (2022)

#406

Earlier quoted context omitted.

its not crazy to me... ive worked at a couple of places that decided to try to use libraries in a web services context. They were all disasters, and the libraries ended up being considered severe tech debt. The practical aspects of updating all the consumers of your library, and how the libraries interact with persistence stores end up being their undoing.

How do you square this with the fact that you likely used dozens of libraries from third parties?

probably 1000s hah. It's the speed of change. third party libraries dont change much, or fast - and you dont really want them to. The software you build internally at a product company with 500+ engineers changes much much faster. And you want it to.

Re: In Defense of Simple Architectures (2022)

#407
post #279
post #153

Earlier quoted context omitted.

Be honest with me, how many jobs have you had that cared about your variety of experiences? I’ve been applying to jobs for months and they’re all looking for go and python devs. I have production experience with both languages, their common web stacks, and many others (ruby, js, php, c#, elixir, erlang, rust). I’ve felt that even mentioning that I have experience with other stacks is a turn off to recruiters and EMs.…

All of them in the last decade. But I guess we misunderstand each-other. None of them cared that I knew "a lot of stuff that isn't appropriate here". For example, a recent gig, hired me because I'm not just another Rails "expert", but a Rails expert with Typescript experience, who built large CI/CD pipelines with containers and has built complex (is there another way?) AWS infrastructures etc. Sometimes they need som…

I envy that position.

Feels like because I didn’t work in go or python at my most recent job, I’m having trouble landing anything. (I have 5 years of golang prior to my most recent job)

My experience working in devops doesn’t seem to matter for SE positions either.

Re: In Defense of Simple Architectures (2022)

#408

Earlier quoted context omitted.

> I've never really understood why you couldn't just break up your monolith into modules You can! We used to do this! Some of us still do this! It is, however, much more difficult. Not difficult technically, but difficult because it requires discipline. The organisations I’ve worked at that have achieved this always had some form of dictator who could enforce the separation. Look at the work done by John Lakos (and v…

> does not require the strict discipline required in a monolith How so? If your microservices are in a monorepo, one dev can spread joy and disaster across the whole ecosystem. On the other hand, if your monolith is broken into libraries, each one in its own repo, a developer can only influence their part of the larger solution. Arguably, system modularity has little to do with the architecture, and much to do with a…

> Arguably, system modularity has little to do with the architecture, and much to do with access controls on the repositories and pipelines.

Monoliths tend to be in large monolithic repos. Microservices tend to get their own repo. Microservices force an API layer (defined module interface) due to imposing a network boundary. Library boundaries do not, and can generally be subverted.

I agree that modularity has nothing to do with the architecture, intrinsically, simply that people are pushed towards modularity when using microservices.

Re: In Defense of Simple Architectures (2022)

#409

I'm going to agree with Dan Luu by asking where I can find more of these sane companies. I want to spend an honest 6h a working day improving a product (Terraform and Webpack are not the product) and spend the rest of my time tending to my garden.

I think about this almost daily while slogging away in hundreds of lambdas, working on the world’s slowest app server. I think maybe 10% of our effort rubs off as business value. Maybe less.

Re: In Defense of Simple Architectures (2022)

#410

Earlier quoted context omitted.

> does not require the strict discipline required in a monolith How so? If your microservices are in a monorepo, one dev can spread joy and disaster across the whole ecosystem. On the other hand, if your monolith is broken into libraries, each one in its own repo, a developer can only influence their part of the larger solution. Arguably, system modularity has little to do with the architecture, and much to do with a…

> Arguably, system modularity has little to do with the architecture, and much to do with access controls on the repositories and pipelines. Monoliths tend to be in large monolithic repos. Microservices tend to get their own repo. Microservices force an API layer (defined module interface) due to imposing a network boundary. Library boundaries do not, and can generally be subverted. I agree that modularity has nothin…

People make this argument as though it's super easy to access stuff marked "private" in a code base--maybe this is kind of true in Python but it really isn't in JVM languages or Go--and as though it's impossible to write tightly coupled microservices. The problem generally isn't reaching into internal workings or coupling, the problem is that fixing it requires you to consider the dozens of microservices that depend on your old interface that you have no authority to update or facility to even discover. In a monolith you run a coverage tool. In microservices you hope you're doing your trace IDs/logging right, that all services using your service used it in the window you were checking, and you start having a bunch of meetings with the teams that control those services to coordinate the update. That's not what I think of when I think of modularity, and in practice what happens is your team forks a new version and hopes the old one eventually dies or that no one cares how many legacy microservices are running.
Post reply on HN