11 ms·
Should you use a Lambda Monolith, a.k.a. Lambdalith, for your API?
- giorgioz 3y agoWe use Lambda monolith usually with a Lambda containing an entire REST JSON API node.js server. It works very well. I feel one of the reason why Lambda did not gain fast market traction is because all the initial tutorials focused on having an endpoint for each lambda, which is actually a special optmization edge case that can come later. Services like Vercel just wrap the Lambda and indeed deploy an entire server to the Lambda and gained a lot of users this way. Lambda Monolith are good replacement to the old Heroky dynos. Lambda monolith are super cheap for B2B SaaS startups with little traffic
- intrasight 3y ago>Lambda did not gain fast market traction is because... I'll extend this to all three cloud services, and dispute the assertion. Developers are smart and figured out that these serverless platforms are great for APIs even if the initial tutorials didn't present that scenario. Also, the platforms just got better at this over time while those early tutorials were somewhat cast in stone. I've not looked lately, but I would hope that they now have tutorials that show monolith scenarios. >Lambda monolith are super cheap for B2B SaaS startups Again, I'll extend this to Azure Functions and Cloud Run. Truly an amazing place we now sit. My first public facing API required me to build a physical machine and place it in a colo facility in town. Now I just run a command-line or check in my code and my API is live.
- LudwigNagasena 3y ago> I feel one of the reason why Lambda did not gain fast market traction is because all the initial tutorials focused on having an endpoint for each lambda A big reason is that lambdas were half-baked and gradually became better. They are still limited. Sending a binary blob? You have to convert it to base64. Streaming a response? You can only do that on the nodejs runtime. Establishing a short-term ws connection? Hard/impossible.
- intrasight 3y agoThe question strikes me as odd. I can't imagine why one would split an API across separate isolated compute nodes. I've used isolated functions in the context of "message orchestration" scenarios, but I'd never do that for an API.
- anentropic 3y agoCan't help thinking that a lot of best practice advice from AWS coincidentally maximises your AWS lock-in and billing spend
- theshrike79 3y agoI've talked to actual AWS representatives face to face. Every time they tell us how we can spend less money. I've had one tell me that don't try to use this service, it won't work on your use case and if you try to force it, it'll cost you too much to be viable.
- mastazi 3y agoHere's an example: I have one workload that needs more RAM because it will parse some big CSV. So this is in its own lambda with different memory settings. Another example could be permissions granularity (each lambda can have its own IAM role). For example one of your lambdas could have access to something in Secrets Manager. There are also disadvantages to this approach, for example build times and deployment times.
- oulipo 3y agoThe issue for me (using GCloud functions) was the cold boot issues, is this more or less fixed now?
- andrewstuart 3y agoWhy lambda? Just run nodejs. The cloud has made otherwise smart people into unthinking drones. You don’t need any of the cloud stuff, except a Linux virtual machine. Stop drinking the cloud kool ade, it’s making things much more complex and expensive for questionable gain. Learn how to, you know, run software on a Linux computer.
- fuzzy2 3y agoAnd suddenly you have to manage an entire Linux server. (-:
- andrewstuart 3y agoOh the burden.
- kikimora 3y agoSSH keys, security updates, monitoring, access controls just to name a few. How do you stop a former employee from running a bitcoin miner in your servers? How do you detect that hacker has got access to your server?
- HyprMusic 3y agoThere are plenty of cases where lambda is a better fit than hosting a server. Just like there are plenty of cases where it's not an appropriate fit. By flat out refusing to consider it, you become as much of a "drone" as the people you call out.
- andrewstuart 3y ago>> There are plenty of cases where lambda is a better fit than hosting a server. Such as? If it’s regional latency then run a machine in the region.
- diesal11 3y ago
- otteromkram 3y agoWhat's with all the anti-microservices posts lately? Is there a mounting campaign to put software devs/engineers out of work?
- philwelch 3y agoAt least someone finally admits microservices are just a jobs program for software devs.
- TYPE_FASTER 3y agoIf you're going to put everything in a single lambda function that's continually serving HTTP requests, you might as well look at ECS.
- theshrike79 3y agoECS doesn't a) scale to zero b) scale up to infinity near-instantly. Source: I've rand both a Lambda Monolith and ECS on production and would pick Lambda any day
- baq 3y agoDo you scale to zero for the resume achievement or to actually save money?
- grose 3y agoI like to use it for little side projects, then I can leave them alone forever and not have to shut them down.
- theshrike79 3y agoYep, I've got a side project running on AWS Lambda + DynamoDB for maybe 5 years now. It's only now getting big enough that I'm no longer on the free tier. My bills are around $0.02 a month from API Gateway =)
- theshrike79 3y agoTo actually save money. Mostly due to not needing to have a 24/7 team managing it. AWS Lambda NEVER goes down. And if it does, it's most likely someone messing with DNS or backbone routing again and half the world is broken anyway. It does need skill though, the billing model isn't as clear as "you pay me X euros a month for a server, I don't care what you do with it", but it's not dark magic either.
- goostavos 3y agoJust FYI: You can totally scale ECS down to zero. Our ECS bill hovers around $1/mo because we spin it up on demand based on queue size (It takes a painfully long time to spin up, though).
- nickdothutton 3y agoThe distant hum of hornets grows louder as you approach the HN thread. There is no substitute for architecting your service for the market and with knowledge of the computing machinery (which boils down to physics) that will underpin it. By which I mean understanding how it will be used, how it will grow, which parts of it will require “structural strength” and which are “decorative” and how what you are developing will manage to align both with the customers requirements and what the physics of available computing machinery can provide.
- cr3ative 3y agoAh, I see https://en.wikipedia.org/wiki/Betteridge%27s_law_of_headlines https://en.wikipedia.org/wiki/Betteridge%27s_law_of_headline... is still working.
- report-to-trees 3y agoI would argue that instead of starting with a Lambda Monolith and splitting routes out when they need to scale separately, you should be starting with an actual monolith and using Lambdas _only_ when a single route needs to scale separately (in a way that fits lambda). The Lambda Monolith is an unnecessary architecture as far as I'm concerned.
- theshrike79 3y agoSo a separate server running a monolith is not "unnecessary architecture", but a simple Lambda function is? With a Lambda function you can have a dozen different versions of the same code running simultaneously with zero extra cost and none of them will affect each other's performance. Every one of them will be versioned and you can instantly roll back to any version or pick any version to be "production".
- dgroshev 3y agoYou can't if you have even moderately complex storage (like an SQL database). There is only one version of that, and while you can make sure that you can run one other version in parallel, it's just one version and a lot of extra complexity.
- theshrike79 3y agoIt depends on your schema, I've worked with systems where we have multiple clients in a single system, the data was separated with per-client views. And it also depends whether the database is MSSQL ($2k/month on AWS) or something like Aurora.
- deleted 3y ago[deleted]
- report-to-trees 3y agoIf you need multiple versions of something running simultaneously then ya lambda might be simpler. In my experience, running a single monolith server will be much simpler than 20+ lambda "monoliths" that call each other. I think the simplicity of lambdas vs a persistent server looks good on paper but falls apart when you have multiple times more deployments to manage.
- contravariant 3y agoSurely if you're reimplementing an HTTP server inside a function running on an HTTP server then something somewhere has gone horribly wrong.
- Spivak 3y agoDo you feel the same about a load balancer being an HTTP server proxying requests to another HTTP server? Because it doesn't have to be this way, there's php-fpm and such that could eliminate the http->http step
- contravariant 3y agoI'm confused, how does php-fpm connect someone to the right machine? It just looks like basic multiprocessing to me, which should be a basic feature of any decent http server. Unless you're referring to the 'load balancer' in the comments where someone builds their own multiprocessing by launching multiple servers and putting nginx in front of it. I mean do what you need to do but at least be aware you're hacking together something that should be a basic feature of the http server. If you wish to push me I'd be forced to admit that I don't like load balancers either, but that's because they're doing routing on the application layer which is not ideal and creates a single point of failure. That ship has sailed though.
- jvanderbot 3y agoI _just recently_ ported a hobby fastapi project into a lambda container and I can't speak highly enough about it. My costs went to zero, deployment is just as easy, performance went up (lambda is pretty good once warm), and my local dev build matches the API perfectly now. I could get some of that on vercel, but not the docker containerization, which makes all the local/remote stuff work the same.
- Aeolun 3y agoMaybe when you decided to use lambda in the first place, for sure. But when you are stuck with lambda consolidation is best.
- scarface_74 3y ago
- snicker7 3y agoI find managing the AWS API Gateway to be too cumbersome. We use a proxy lambda that handles authentication and has routing logic to other lambdas (or SQS | State Machine).
- theshrike79 3y agoYes, you should. Especially if you want to scale up without tons of extra work. The model of "every function should be a separate Lambda" is just moronic - I've seen people run into hard limits on AWS going all-in on this model. Instead Build a single executable/library and deploy it as a Lambda function. Now you have automatic versioning, just push and it's a new version. You can label versions and call them based on labels. Deploying to prod is just swapping the prod label to a new function. Want to roll back? Swap it back. Credentials: ran a top10 mobile game backend on AWS Lambda with zero issues using a C# monolith.
- Aeolun 3y agoAWS limits are there to be worked around! Have too many lambdas to fit them in a single cloudformation stack? Just split it up into ‘per family’ stacks. Enjoy your nested cloudformation stacks. Oh, you say you have more than 200 endpoints in your REST API gateway, and suddenly your CloudFormation stop working? Yes, unfortunately CF only load 8 pages of resources in alphabetical order when starting, and your root resource starts with a ‘Y’. No problem, implement a new custom resource that just creates and discards API gateways until you have one with your desired root resource starting with ‘A-F’. Did I mention the ‘delete a rest api’ API is limited to a single call per minute? The fun doesn’t end. Now you may be able to grow until 600 resources before you’ll have to tighten the limits once again. You say you think this is bollocks? Of course, just switch to an Application Load Balancer. Just 100 rules max means you’ll only need to nest about 4 of them to fit all your API endpoints. And people wonder why some give up on the cloud. Any $5 VPS has higher limits than any of these AWS services…
- kikimora 3y agoWhy not 1 ALB in front of a Lambda with a router inside it?
- theshrike79 3y ago200 endpoints? Sheeesh. I've never seen anything over 50. That must've been a proper monolith then? =)
- rco8786 3y agoI worked on a small SaaS that deployed in this way. The AWS bill was about 10x what it would have been if they had just deployed nodejs on an EC2 instance.
- deleted 3y ago[deleted]
- lsaferite 3y agoThere's obviously a static load level where it makes more sense to have an always-on server vs. a FaaS and you need to monitor that boundary point. The point of doing something like this "Lambda Monolith" is that transitioning to an always-on server is trivial. I've been doing this exact setup for a while and our static costs basically evaporated. Seeing your costs drop below a dollar/month on a project you are building is amazing. As soon as one of our projects is large enough, we move it to a dedicated instance or cluster. This allows us to delay that point until we have enough revenue to justify the costs.
- fidrelity 3y agoI just can't get my head around this argument of 'scales to zero'. If you have one or more professional developers working on a project how can you be bothered about an extra $20-$200/month when you know you'll also be spending a couple of engineering hours (worth more than $200) on migrating later?
- calderwoodra 3y agoI feel exactly the same way - this idea of a lambda monolith seems applicable to hobby projects only.
- kikimora 3y agoScales to zero means you can span as many environments as you want and don’t bother. Every dev can have multiple environments to demo features and do experiments.
- knodi 3y agoAlso the fact that lambda it will limit the tech you can use in the backend such as long-lived connections stack (redis, postgres)
- bob1029 3y agoYes, but not only API... We figured out how to get Azure Functions to serve a complete webapp without any extra crap wrapped around it. No gateways/proxies/etc. One function that serves the root URL[0] and has conditionals for GET/POST methods. Beyond this point, anyone with old-school mastery of HTML/CSS/JS can get the rest of the job done with basic-ass SSR and multipart form posts. For data, we just use Azure SQL Server. Authentication is like sticking legos together now. 100% managed identities, no magic strings, etc. Our functions get the user's claims principal right in the arg list. We have zero lines of authentication code in our latest products. This stuff is absolutely the future for a vast majority of boring old business. One thing to think about: If your FaaS offering is capable of serving content-type of application/json, is it not also capable of serving content-type of text/html? Do your providers go out of their way to prevent you from making a simple solve on 99% of B2B bullshit? [0]: Note that serving the root URL on an Azure Function is an undocumented hack-around item. Worst case, we would serve the /app route and our users (B2B) wouldn't really care. My suspicion is that Microsoft detected our use case and saw that it stole a LOT of thunder from a wide array of other Azure offerings (API Gateway, Front Door, et. al.), so making it slightly more complicated (at first glance) is likely intentional.
- scarface_74 3y agoWhy would you ever do this instead of just storing your static assets in the Azure equivalent of S3 and let it do the heavy lifting along with the CDN?
- bob1029 3y agoWe are B2B at the scale of 1-10k users. There is no "heavy lifting" to do in our contexts of use. Serving static assets along with the SSR content is totally acceptable. They aren't even served as separate files. We inline everything into 1 final HTML payload always. Our largest assets are SVG logos that our clients bring to the party. We do work with dynamic PDF documents, but these are uncachable for a number of reasons. Hypothetically, if we had millions of users and static asset IO was actually causing trouble, we'd consider using a CDN or other relevant technology.
- 3y ago
- icedchai 3y agoI've seen it both ways. A lambda monolith is much simpler to work with.
- hk1337 3y agoNo. It's a gross misuse and misunderstanding of serverless and lambda functionality.
- meowtimemania 3y agoHow so? Lambdalith means simpler, faster deployments, and easier to run locally.
- mastazi 3y agowith lambdalith you miss out on some things like granular IAM roles and granular Memory/Cores config. Also with lambdalith you probably end up needing an application framework as opposed to just using mostly vanilla features of your language of choice. Of course I agree that lambdalith has advantages as well.
- kikimora 3y agoI don’t buy this. From the top of my head I can think of many things not handled by the Lambda runtime: session cookies, routes with ids in them like /author/15/posts, having to specify Content-Type for responses, generating error responses properly, etc. Good server framework does this for you transparently.
- mastazi 3y agommm sure but I never said that the Lambda runtime handles those things... By the way, routes with ids are handled no problem by API Gateway, you can even set more complex ones like {proxy+} etc.
- kikimora 3y agoMy comment mostly relates to this > Also with lambdalith you probably end up needing an application framework as opposed to just using mostly vanilla features of your language of choice. The point I make is even with lambda per endpoint you need many framework features.
- meowtimemania 3y agoIn most cases I prefer monolithic lambda functions. It means faster deploys, and it's easier to reason about. I create separate lambdas only when I have some large dependency that can be easily be separated from the rest of the application.
- lstodd 3y agoOMG. An application server reinvented. Another couple of years and they will reinvent microservices on top of that monolith thingy.
- kennu 3y agoTypical usage is one Lambda per service. Then use switch (event.routeKey) { case 'GET /path: ... } to serve the different API Gateway routes attached to the Lambda. It doesn't have to be very complicated.
- mastazi 3y agoThere is a third approach besides "lambdalith" and "one lambda per route", it's making one lambda for a group of routes, for example you could group them by first segment of their path (all routes starting with /users/* in one lambda, all /orders/* in another, etc). Then, inside the lambda handler, you can use a routing library to select the right method. This worked for us because it mitigated the shortcomings of the other two approaches for example: - lambdalith: very long build times and long deploy times (due to the high number of lambdas) - one lambda per route: lack of permission granularity (as opposed to creating different IAM roles for different lambdas); lack of granularity for memory/cores configuration means you are missing out on cost optimisation; also, as the API grows, it soon becomes necessary to adopt some framework like Express or Fastify to keep things tidy. EDIT: reworded last paragraph for clarity.
- danielrhodes 3y agoI've used Lambda at some scale. I think Lambda is pretty great. You can really be batting far above your weight by utilizing AWS services. It's especially great and cost effective for spiky workloads, with the exception of a few services like DynamoDB. But there are trade offs that I learned. You might not see this with a small setup, but you definitely will the bigger you get. A few that come to mind: 1) AWS services are not easy to develop with locally. This incentivizes a lot of testing in production, which in turn can slow down development speed and increase defects. Yes there are some wrapper libraries and helpers, but it's not 1:1. (This same thing applies to Cloudflare workers as well). 2) Lambdas have constraints such as execution time limits, and a lack of fine grained control over resource usage. This makes it hard to use things like long lived requests and web sockets. But it can also mean you could end up paying a lot more compared to a fixed price setup, such as an instance in EC2. The flip side is also true: it can be an incredibly good deal as well. 3) There's a lot of tooling and knowledge around Lambda which takes some time to learn. You have to be quite careful around things like DB connections, logging, concurrency, and so on. This overhead might ultimately make things more complicated than a more traditional setup. 4) There is a maximum package size for a lambda. When you include all your dependencies in NodeJS and so on, it can become very tricky to keep things under this size in even a medium sized code base. A larger size also effects your cold start time. There isn't a lot you can do to change this. 5) Lambda's easy integration with other AWS services is both a blessing and a curse. AWS is not cheap, and given how trivial it can be to add on services, it can require a considerable amount of time to reduce spend. Lambda's integration with non-AWS services is very hit or miss (e.g. Kafka). You only find this out by getting very burned. 6) If you require anything like C libraries, be prepared to spend a lot of time working on builds and deployment - or sometimes it just magically works. You are operating inside a somewhat opaque environment, and it can require a lot of fiddling. Additionally, using tools like CloudFormation do not scale very far, and can sometimes result in quite bad outcomes. This stuff can steal a lot of time. 7) There are hidden costs everywhere. For example: Are you being a good engineer and adding a lot of visibility by logging and using tools such as CloudWatch? Be prepared to pay an extraordinary amount relative to the value you get. 8) Using lambda as a processing pipeline? Easy to get started, hard to get reliable. AWS does not have good inexpensive tools to manage these well, and you can end up with a very leaky and expensive system. 9) You would be surprised at how many bugs and weird behaviors exist when these AWS systems play together. In some cases, the only recourse was to delete the entire stack and redeploy because something got stuck. That could be quite bad depending on the use case. 10) Using lambdas over data engineering tools (e.g. Kinesis Data Streams vs Spark) might actually be more complicated. You should hopefully be familiar with and have some experience in this these tools before making a decision when its time to build.
- locustmostest 3y agoWe use what might be called a microlith pattern with Lambda for our "infra meets code" document handling project (https://github.com/formkiq/formkiq-core https://github.com/formkiq/formkiq-core). There's nothing stopping someone from taking what we have and porting to an EC2, but for most use cases, this pattern seems to work best. We break our Lambdas up by how they are used, to keep sizes down, with the option to break up further if we need to.
- joshstrange 3y agoI actually agree with a lot of what they said here but the last half or so of the blog post was incredibly hard to follow. The gray blocks were what he was refuting/replying to? The X/check emojis meant he agreed or disagreed I guess? It made me think that emoji applied to the paragraph it was part of, as in "I agree with this ->" or "I disagree with this ->" when I think it meant I agree/disagree with the gray block _above_. It was hard to keep reading and so I stopped > Now the big one, reusing code is by far easier in a monolith. > Consider the scenario for patching an error in a library that is used in all your single-purpose functions: > You have to publish shared code into packages that need to be used by all of your routes > You would have to context switch, make the change in the library, merge, publish the package > Then context switch again and update the version in each of your 100’s of routes to use the new version > Then you need to test and deploy all the 100’s of routes I don't use a monolith mainly due to size. I had enough problems packaging all my functions in 1 archive and hitting size limits that I can't imagine a monolith would do anything but lock me into that issue with no solution other than splitting it up into smaller services. Currently I package all my functions individually so they only contain the code/deps that that specific function needs. This works very well and keeps my function sizes small (except for the Prisma engine, stay away from this if you can). Also I have shared code that multiple function use (wrapping code for catching errors, DB access, various other reusable services), it all works just fine and I don't package/publish my shared code, my packaging grabs what each function needs and includes it. Everything else he says, especially about getter /more/ warm starts and being able to really take advantage of PC is true, but the size issue steered me away from a monolith. If size wasn't a problem I'd probably be running express in my lambda but instead I have a 1 function per endpoint and that seems to work pretty well for my company.
- alunchbox 3y agoDon't see the reason too. I mean I get it for a first project or while learning, but once you 'get' lambda using it with CDK or another framework makes you realize the whole reason for lambdas being about transformation of data not the transportation of data. Small functions that can be reused in multiple APIs, tiny deployments, small tests incrementally building a system. Lambdas primarily shine in an event based system. I'd rather use the serverless tooling as they're intended i.e cognito, gateway, event bridge, dynamodb. Each are designed to solve a particular problem in what I'd say as a different paradigm. If you want a traditional monolith I'd look to fargate instead since you'll be rolling a permission system/auth system and probably a framework of sorts. In my past using only a part of lambda eventually lead me to having to build an already solved problem with a serverless service and make it fit in. Lessons learned I suppose.
- jamietanna 3y agoRelated: https://www.jvt.me/posts/2021/11/17/java-serverless-learnings/ https://www.jvt.me/posts/2021/11/17/java-serverless-learning...
- pshirshov 3y agoYes, that's what I do with Graal Native Image and multi-entrypoint applications ( https://izumi.7mind.io/distage/distage-framework.html#roles https://izumi.7mind.io/distage/distage-framework.html#roles ). Not only for APIs, but for everything. Microservices in various forms are unnecessarily distributed and that's a fundamental problem with many implications. When you pack your components into a monolith which can be easily reconfigured into microservices by replacing transport implementations, you would gain a lot.