12 ms·
How to design software architecture for startups
- cbuu 3y agoThere is a lot of information out there on how to build software for enterprise systems. If you are designing a system for a startup, a lot of these patterns and techniques simply don't work well. High levels of uncertainty, the need for maximum flexibility and a quick pace as well as serious restrictions in (wo-)manpower are challenges that are often unique to startups. On the other hand, startups can make compromises that enterprises can't make. Here is how we did it.
- m_a_g 3y agoIt looks like monoliths are officially back in fashion.
- weego 3y agoGetting to market so you can get the next found of funding or start making a profit is always in fashion. Whether you did it perfectly right once you get there is the correct "technical debt" problem to have as a burden.
- NoMoreNicksLeft 3y ago"We're very worried about tech debt. If we don't get this perfect now, we'll forever be flailing around trying to make it work even as other teams add worse baggage to the wrong pattern you laid down. We'll never have time to go back and fix it." -- No one ever.
- letsdothisagain 3y agoThis made me think of Twitter's "fail whale". And then I remembered that mess of spaghetti PHP sold for 44 billion dollars and now I'm rethinking my life.
- malikNF 3y agoThe older I get, the more I understand my seniors.
- javcasas 3y agoWelcome to seniorhood. Also get out of my lawn.
- jcadam 3y agoThis. It's hard to manage a dozen services with only 1-2 devs - especially considering you're solving a problem you don't have yet, and by the time you do, you'll have more devs to handle/justify the complexity.
- tacker2000 3y agoI dont think they were ever “out of fashion”, it’s just that the people pushing microservices were extremely vocal about it.
- rwoerz 3y agoIndeed. I never understood how they got synonymous to "big ball of mud". When I think of a monolith, I think of something heavy with a very simple structure like the Washington Monument.
- mjr00 3y agoI do worry the pendulum will swing too far the other way. Having a separate Lambda function for every web request "because microservices" sucks, but having a single codebase worked on by 200+ engineers also comes with a lot of problems.
- dopidopHN 3y agoExactly, I do appreciate micro services but not for the technical aspect. They shine in large cove base where at least a handful of teams are responsible for some services and not other. So you don’t have to get in there backlog too much.
- winrid 3y agoHave a folder/subproject per team?
- mjr00 3y agoThis helps, but doesn't fully solve the problem. You still end up using the same runtime so it's not like the teams are fully independent. Classic problem is you have a /Team1 and /Team2 folder (or library that gets imported, doesn't matter). Team1 needs to upgrade to pandas 2. They try, but wait, Team2's code depends on Tensorflow which depends on pandas 1.x. You are now in dependency hell[0] and need to do something unpleasant, whether that's forcibly updating everything in that pandas/TF/etc dependency chain, which can be a long and painful project in large codebases, if it gets done at all. Or doing JAR shading or fork-and-rename to be able to support both pandas==1.x and pandas=2 in the same runtime, which may not even work in pandas' case. Or the most common thing, which is just give up and stick with comically outdated libraries and runtimes for way too long. Hello, Java 6/7. [0] https://en.wikipedia.org/wiki/Dependency_hell https://en.wikipedia.org/wiki/Dependency_hell
- winrid 3y agoNo suggestion will fully solve all the problems. Are you looking for silver bullets in HN comments? :) I would rather deal with folder per team in same repo than services spread across multiple repos that still depend on common libraries/utilities/databases, which has happened at most jobs I've had, and it's a mess.
- JustSomeNobody 3y agoI wish blogger driven development would go out of fashion, but I guess it never will. People need to be engineers. Stop trying to figure out how to solve your problem by copying what others have done to solve theirs.
- javcasas 3y agoWhen I researched it(around 2017), most microservices sucess stories began with "our monolith couldn't scale beyond our 200 devs, 300000 clients and 150 millions of revenue per year, so we had to do something". So, how did you manage to go from nothing to 200 devs/300000 clients/150M of revenue? Exactly, with a monolith.
- yawnxyz 3y agoThis still feels super complicated... idk I just used Sveltekit + Airtable and Notion as CMS (cached with Cloudflare). Deployed on Vercel's free tier. Cloudflare workers for certain functions (like grabbing stuff from Notion), and now FastAPI / Fly.io for langchain stuff. And that's it. Of course, we're not anywhere high # of users or profitable, so this might all just fall apart tomorrow.
- dpflan 3y agoWhat’re you building?
- deleted 3y ago[deleted]
- deleted 3y ago[deleted]
- optymizer 3y agoStopped reading at chat server. Some FAANGs use IRC when all fails. There is no reason a startup should be building a chat server in 2023. Best reason given in the article was 'integrations'. Use an IRC bot to post messages to the channel, don't waste time writing yet another insecure chat client and server.
- elbigbad 3y agoBut then the length of the article wouldn’t seem substantial and you wouldn’t bother reading it at all because you’d assume it wasn’t worth your time and the author wouldn’t get to tell you about whatever random app they’re building and shilling for. Key insight: the article isn’t about the tech, the article is about them trying to drive traffic to their app or whatever.
- antoinealb 3y agoIsn't the chat server they talk about for somethin in-app ? Like if your game offers player-to-player chat, or something similar ? I don't think they are talking about tools for software engineers themselves.
- bicijay 3y agoAn external chat service can be a pain in the ass just like a microservice. Depending if you want a lot of business rules integrated in that chat, you will have to keep data synced between your server and the chat's server. This can become a nightmare if you dont get it right.
- klabb3 3y ago> An external chat service can be a pain in the ass just like a microservice. Of course, because it’s just someone else’s microservice. Socially, it’s nice to have someone else take care of it. But technically, it’s more opaque than even your own microservices. > Depending if you want a lot of business rules integrated in that chat, you will have to keep data synced between your server and the chat's server. Right, because both the chat and your core service share users. So the boundary criteria for microservices, ie being standalone, is not there with chat, or many other types of services. From a technical perspective, these services would be better suited as libraries that require some integration work. However, that’s not conducive to usage based pricing, which is the snake within the microservice oil bottle.
- krishadi 3y agoSimple answer: don't build anything yourself if you can find something that fits 80% of your use case.
- agloe_dreams 3y agoWith one caveat: don't force a round peg into a square hole. If it works for 70% your use case but the last 30% is mission critical to your whole business and it doesn't really work for that, even with minor mods, be willing to find better ways.
- esafak 3y agoOutsource peripheral technologies, build core technologies.
- letsdothisagain 3y agoAnd this is why I use Oracle Apex lol
- deleted 3y ago[deleted]
- mjr00 3y agoI hate to be the guy who says "you aren't doing services right," but... you aren't doing services right. > Each service has to be maintained and deployed and increases the boilerplate needed for shared data structures, complicated communication protocols and infrastructure. By the time we released our app, the common library used by most services has been updated over a hundred times. And every service has to follow suit eventually. Shared data structures? Common library? Services have an API. If you are sharing data structures and a common "core" library across services, yes, you are officially doing it wrong. From the architecture diagram it also looks like there's only one MongoDB instance, which, if you have multiple services talking to the same database[0], is also a major sign that you're doing it wrong. IMO the author came to the correct conclusion, that monoliths are better for a new project, but for the wrong reasons. Or maybe the right reasons which aren't clearly explained, which is that at the beginning you don't have a good enough grasp of the domain to properly separate into independent services. [0] yes, there are exceptions where you can have multiple services use the same physical database to reduce maintenance overhead, but enforce separate ownership through different logical databases or even table-level permissions, but I'm assuming that wasn't done here.
- cbuu 3y agoAbout the MongoDB instance: It's indeed one physical instance but each service owns its own database. Thank you, I will make that more clear.
- beembeem 3y agoIt's a replicaset at least, correct? Hopefully not standalone
- tmshkr 3y agoWhat is wrong with sharing a single database between services? Seems like a pretty commonly accepted pattern: https://docs.aws.amazon.com/prescriptive-guidance/latest/modernization-data-persistence/shared-database.html https://docs.aws.amazon.com/prescriptive-guidance/latest/mod...
- sktrdie 3y agoI feel like the quickest I've ever moved and most innovative stuff I've ever done comes from doing it the "hacky" way. At our latest setup we're just relying on Framer (framer.com) to build all of our UI components using a free drawing canvas. Then for more customization we have a setup where devs can just spin up a CodeSandbox link in the browser that imports the Framer component to add more interactivity (like custom hooks etc). Everything is deployed via CodeSandbox. Devs/Designers/Anybody else just use CodeSandbox links, no editors. People responsible for content use these links to edit .json files inside CodeSandbox repository to quickly add/edit things. New images can be uploaded via drag & drop in and when saving the file it becomes part of the git repo. No CMS needed. We have a bunch of lock-ins with this setup (like if Framer/CodeSandbox goes down we're f**ed) but I feel like going with anything else there will always be lock-in (AWS, Vercel, some open-source project which is now dead and nobody can maintain anymore). It's amazingly fast to work this way & we love it.
- totalhack 3y agoInterested in learning more about the codesandbox workflow. We use Webflow for the flexibility and abilities it gives a small team with some non-engineers, but I want to move off of it if I can find a solution that maintains some of the benefits while addressing some of the drawbacks. Is there any content you can point me to that inspired this?
- derenge 3y agoWhat are the main drawbacks you see with Webflow?
- felipesabino 3y ago> Splitting your codebase into multiple independent services comes with a lot of disadvantages: Each service has to be maintained and deployed and increases the boilerplate needed for shared data structures I think the author got "separate and isolated services" with "separate and isolated source code", they are not the same
- SPBS 3y agoI was expecting something like this article https://alexkrupp.typepad.com/sensemaking/2021/06/django-for-startup-founders-a-better-software-architecture-for-saas-startups-and-consumer-apps.html https://alexkrupp.typepad.com/sensemaking/2021/06/django-for... (discussed at the time https://news.ycombinator.com/item?id=27605052 https://news.ycombinator.com/item?id=27605052) but was greeted with something far more abstract and less helpful. Look at the difference in quality of their table of contents! - What does our app do? - Microservices usually don't work well for startups - Move fast and outsource things - Consider building reusable things - Be pragmatic - Boundaries along sync/async communication patterns - How we did it and how we would do it next time - About flexibility - Predictability - Rule #1: Every endpoint should tell a story - Rule #2: Keep business logic in services - Rule #3: Make services the locus of reusability - Rule #4: Always sanitize user input, sometimes save raw input, always escape output - Rule #5: Don't split files by default & never split your URLs file - Readability - Rule #6: Each variable's type or kind should be obvious from its name - Rule #7: Assign unique names to files, classes, and functions - Rule #8: Avoid *args and **kwargs in user code - Rule #9: Use functions, not classes - Rule #10: There are exactly 4 types of errors - Simplicity - Rule #11: URL parameters are a scam - Rule #12: Write tests. Not too many. Mostly integration. - Rule #13: Treat unit tests as a specialist tool - Rule #14: Use serializers responsibly, or not at all - Rule #15: Write admin functionality as API endpoints - Upgradability - Rule #16: Your app lives until your dependencies die - Rule #17: Keep logic out of the front end - Rule #18: Don't break core dependencies - Why make coding easier? - Velocity - Optionality - Security - Diversity
- gpjanik 3y agoThis is a really cool and very opinionated post that sums things up to a coherent recipe that will work very well. There are different ways to achieve this (also with Django/DRF), but the purpose of this one is to make it specific to Django's implementation. I think the OP meant more general advice on architecture altogether.
- gpjanik 3y agoI would add: - Don't build your CI/CD pipelines; use Vercel or something similar - Don't use message queues, crons and anything that can by design cause race conditions until absolutely unavoidable - Use a framework if you and your team know one well (e.g. Django Rest Framework), otherwise use whatever you know inside out even if it doesn't have all the features you need - or you'll end up slowing down painfully at every other complex bug - Using TypeScript for both backend, frontend and the domain simplifies a bunch of things (configuration, types) - Unless you're building ML pipelines in parallel to a web app (or some similar clear technological separations exist, e.g. web interface and an UE5 game), you should use one programming language. All your developers should know the app A-Z in the early stages. - Your product is unlikely to succeed overnight but likely to die because of overengineering. You should worry about scaling, but only a little bit. - Forget using JWTs if you're in some sort of regulated field. Any sensible white/greybox certification for insurance (and that's often a requirement for running a business) will require you to have "log out all devices" option.
- cybrox 3y agoOn a project I worked on, we implemented a "log out all devices" option and similar security features by building a simple deadline system on top of using JWTs. Every user's data contained among other things a deadline timestamp, which was (re)set every time a security relevant data point was changed (password, 2FA, log out all devices, etc...) When authenticating a user, services would check for both the JWTs validity (iat, nbf, exp), as well as the cached deadline (iat >= deadline) using a shared auth library. I'd be happy to learn more about the downsides but for as long as this was in place, it has worked really well.
- Zetice 3y agoThe whole point of JWTs is to not check some other value in the backend. Once you're doing that you've lost the major value of JWTs. So yeah, once you start doing DB calls for every. single. request. you're going to have a lot more options, but JWTs are meant to avoid that. My understanding is the "right" way to do this is to maintain a CRL.
- kaon123 3y agoThanks. This was exactly the app I wanted to build :)
- NHQ 3y agoAdvice versa. Architecture designs, not the other way around.
- agentultra 3y agoThere are few principles that hold, I've found, when it comes to designing software at a startup. Most companies of this size might not be around in a few years. For those first few years it's a good practice to refrain from thinking about the company as a software company (the notable exception being a startup that is literally building software products like libraries, databases, compilers, etc... then disregard this advice). It's a business trying to find product-market fit that happens to use software. Under this lens it doesn't make sense to start writing software if you can avoid doing so: the company might not be around in the next year or two if it can't land those first customers and start growing. The less you write, the less you have to maintain, the more you can focus on what matters: finding that product-market fit. This means optimize for doing the least amount of work and writing the least amount of software possible. Use frameworks (code you didn't write), libraries (code you didn't write), and services (code + infrastructure you don't maintain) as much as possible. TFA points out several of these: use an auth service, use a PaaS, etc. The majority of your "software" often looks and feels like glorified configuration. You're pulling together frameworks and libraries on top of services that do most of the work for you. Good. You've kept your capital costs down and didn't spend time building something you're going to throw out at a moments notice! It's when you gain traction and your services bills start ballooning and your customers start to demand transparency, reliability, that you need to start thinking about hosting your own software and building an architecture that suits your applications' usage patterns. This generally happens after the business has found a niche and is now focusing on adding customers rather than finding them.
- cybrox 3y agoI agree with most of what you wrote but I strongly disagree with the fact that customers starting to demand reliability is a scenario that should happen before you start thinking about hosting your own software. Treating stability and reliability as an afterthought is one of the main things that's wrong with the tech industry at the moment, I would argue. It's a competitive market. Move fast and break things but at least have the requirement to be as reliable as possible from the get to. Alas, this is written from a user and tech enthusiasts standpoint. I know it's a futile argument since reliability is not a requirement for growing a project far enough to get a worthwhile exit, so we will continue to "enjoy" unstable products.
- davidw 3y agoWhat are people using for auth these days?
- jossclimb 3y agoI implemented it myself in Go using github.com/golang/oauth2 and github.com/golang-jwt/jwt.
- davidw 3y agoThe article mentions "Auth services, obviously". I'm curious, because to me it seems like people have mostly used open source things they include in their apps.
- deleted 3y ago[deleted]
- AntonCTO 3y agoKeycloak is good for most use cases. I heard that some teams failed with Cognito (AWS). But for the current product I built my own server. I was tired of fighting some Keycloak specifics like - No "stay logged in forever if you use the (web) application from time to time". - Bugs around caching (especially in integration tests). - No zero downtime deployment (should be fixed soon, too late for me) - Weaknesses around configuration. I used to use keycloak-config-cli, which is good enough for most use cases. And some missing functionality that needs to be implemented very often, like "Accept ToS before profile is created". Having said that, Keycloak is a very good product and I haven't found a better free and open source product. But sometimes it is not the right choice. By the way, I personally don't plan to outsource user data and credentials to a 3rd party service. Although Auth0 is very sexy.
- tmountain 3y agoPocketBase, Supabase, Firebase… all your base are belong to auth.
- vrglvrglvrgl 3y ago[dead]
- gabereiser 3y agoA better title would be "How to f#ck up architecture in your startup". Sharing data models. Sharing database. Good lord! This is NOT the way. Your service has an API. You're service should only be called using that. It's client models are json or protobuf or <insert meta>. You don't need to share anything other than maybe a CI environment and a JWT token.
- legulere 3y ago> Auth services, obviously Isn't it easier to do simple cookie based session token authentication simpler for the beginning?
- AntonCTO 3y agoFrom my point of view, yes, it does. And in most cases there is nothing wrong with it. Just not hyped. Probably, the only real reason to use something like OAuth2.0/OIDC is single sign-on. (BTW, probably all SSO providers use cookies and sessions to maintain their own user state).
- gonlyplease 3y agoHow is you app going (retention, user growth)? Is it only for private happenings or do you have public events in it?
- manv1 3y agoReally, the question here is "do you build a general-purpose solution or one customized to your use case?" I'm not sure where things are these days on the design spectrum, but I think there's still a bias towards "reusable code" and "abstraction." But why? If it's code for your MVP, the future is uncertain, and time is more important. Are you really going to reuse this? You're probably going to rewrite it in chunks. Design it for that. One thing to watch out for in a "shared" architecture is update hell...in the sense that you have so many dependencies that you're basically forced to update everything all at once because of the way you've structured things. That's a fucking nightmare, especially if the various parts have different update latencies. Your app needs approval from the app store, so if it shares something with the back end you literally need to trigger your backend update when app approval occurs. And you have to ensure all your clients update at the same, time, which is unlikely.
- ltbarcly3 3y agoLets start with the assumption that what you are doing at a hypothetical startup is already pereto efficient. That means that if you attempt to improve your architecture in one way it will mean a trade-off against something else. The most common sort of trade-off like this is how long it takes to make some change to the product vs how scaleable the architecture is. Another might be the total effort to make a change vs the ability for multiple large teams to work on the product in parallel. If you are a startup and you have not had at least one phase of explosive growth which proves your market fit exists and you have found it, then you should always optimize for a solution that is just 'good enough' in every other way, but is the fastest possible to build and ship changes. You will die from not finding market fit, and if you find it you can turn your attention to scaling the product, or whatever else you have to solve. Don't 'design your data architecture' until you have to. And for the love of god, never use micro services at a company that has less than 500 software engineers. Microservices are *BAD* for everything except allowing lots of people to work together. It is the most complicated, least efficient possible way to build software except where you have no other choice, which you almost always do.
- zoogeny 3y agoI've been tinkering with a project and one thing that stands out to me is cost. For example, I had a super simple architecture on AWS with 2 load balancers in front of 2 ECS services running on Fargate. Using the smallest possible instances that simple system was costing ~$3.50/day or ~$100/month. That included basic things like the Route53 entries, certificates, the load balancers, the ECS containers, AWS code pipelines running a couple of times a day, S3 buckets for logs. It did NOT include databases, SQS queues, Redis/cache services, monitoring. Just one web server and one api server. I'm not a novice with AWS but it is easy to get comfortable spinning up idealized service architectures without calculating the costs. Even at meagerly funded startups it is no big deal to spend $1000/month on infra costs. But I am not really interested in forking out that kind of money for my weekend hobby projects. It is just not financially reasonable for me to have multiple micro-services alongside multiple databases, caches, CDNs, queues, etc. Even when I consider having my own EC2 cluster backing my ECS services (probably a cost savings but I haven't investigated) I feel confident the cost will be significantly higher than just building a monolith and obviating the need for multiple load balancers, queues, multiple databases, etc.
- ttymck 3y agoWhy couldn't a suite of microservices and supporting datastores be deployed on a single instance (via docker compose, et al.)?
- zoogeny 3y agoI suppose it could. I'm spoiled in that the places I have worked on micro-service architectures had either massive kubernetes clusters with 100s of services or were using ECS backed by EC2. I have an intermediate level understanding of those deployments, how to make them robust and scalable, etc. After seeing the bill I even considered looking into a single instance deploy of multiple containers. Outside of running my own kubernetes cluster I was aware of some blog posts I had read on using docker compose for production. I have no production experience doing this so I don't know how to make it robust, secure, scalable, etc. I could learn. But then I remembered a tip on optimization I learned while I was working in the video games industry. I was working with a guy who was focused on performance optimization. He told me that a common mistake junior engineers made when given optimization problems was that they would try to make the code faster as their first step. One way that is a mistake is to assume something is taking a lot of time without profiling first. But another mistake is to optimize a process that can be eliminated. He quipped: The fastest thing you can do is nothing at all. So rather than optimize container deployments ... why not eliminate them? That honestly seems faster to me than trying to productionize a docker compose deployment just so I can say I am using micro-services. I mean, as this post and many others have mentioned - micro-services add complexity already. It seems more optimal to me to remove the micro-service complexity and save myself the hassle of fighting with docker compose or whatever other single-instance solution might exist. And if I get solid ARR and I feel fine spending $1000/month on infrastructure, I'll probably just use a managed container hosting solution. I've split up a lot of apps into micro-services and in general it is very easy to do when needed.
- deleted 3y ago[deleted]
- lincpa 3y ago[dead]
- hnaccountme 3y agoConway's Law