Ask HN: Solo-preneurs, how do you DevOps to save time?

356 points by aristofun ↗ HN
When you're 1 man show (or tiny team) working on some web oriented application beyond POC level and beyond heroku (for whatever reason) — managing your CI, deployments/rollbacks, DBs etc. looks like a nightmare to me.

Just properly setting up and maintaining a small k8s cluster looks almost like a fulltime job.

I wonder how do your CI, deployment workflows look like?

Any particular tools, practices, guidelines, architecture patterns to reduce pain & timewaste?

How do you CI => deploy/rollback stateless instances? How do you manage your DBs and backups? Etc.

327 comments

[ 5.6 ms ] story [ 289 ms ] thread
I do it KISS. Deployment for me is always a git hook, usually with a private gitea server. So I have versioning and rollbacks available with a cute UI if necessary.

DBs run side by side and are simply backed up regularly with whatever backup solution the VPS offers.

That's it.

Out of school I put way more effort in building my infrastructure but in reality a good VPS, something like Cloudflare and some app based caching can run millions of daily views over 20+ different apps without issues.

Edit:// it's mostly rails apps I host btw. For my wordpress installs i use dedicated VPSes because those scale horrible.

> Out of school I put way more effort in building my infrastructure but in reality a good VPS, something like Cloudflare and some app based caching can run millions of daily views over 20+ different apps without issues.

I read such messages (and also agree to it mostly) and then I encounter my peers wanting active-active clusters with K8s on top or something and I feel I like a dinosaur.

Refreshing to see KISS still being used. Also gitea. What an awesome piece of open source software.

Don't fall victim to resume-driven development; keep on KISSing.
I like this answer, but could you expand a bit on why gitea? Never used it myself, but it looks like self-hosted OSS clone of GitHub? If so, my instinct (in terms of KISS) would be to just use GitHub, so I don’t have to set up and maintain my own thing. What made you decide to go with gitea, out of interest?
GitHub would be the opposite of kiss in my opinion. External dependencies and pushing to remote servers are just pain points.

> git init --bare

On your remote server is all you need to spawn a repo to push to, usually hook examples already included.

The hook can then directly checkout to my live directory, run migrations and restart the server without weird remote automations after every (or specified) push.

Gitea is just a little extra (setup once, touch never thingy) for quick edits and checks (it's a wonderful lightweight piece of software too)

That's easy, Render.com (it's like if Heroku were designed in 2021, and a lot cheaper). And can handle docker and distributed Elixir out of the box as well as free static sites). Took me just a few hours at most to set up and has been very reliable (I think it's k8s on Google Cloud under the hood but it's all abstracted away).
(comment deleted)
I use https://www.hatchbox.io/ , like Heroku (git based workflow), but you can choose what infrastructure you run on.

Hatchbox manages the deployment, backups, rollback etc.

I pay money so I can sleep easier at night!

Envoyer and Forge for PHP stuff.

Render/Heroku for node.js stuff. Netlify for static stuff.

For the more complex bits I have, I use Pulumi to manage everything through IaC. It's still complex but at least it's robust and I can sense-chech changes to infra through a PR to myself.

I've been using Beanstalk for my new project, which is like an in-between for full on AWS and Heroku, but if you need you can decompose it into individual AWS components. It's more difficult to get started and there are way less sensible defaults, but I still got everything deployed for my POC in less than 4 hours.

As for DBs / engines and such, I try to go for hosted services as long as they're not stupidly priced. I'm currently using Elastic cloud. If I need a relational DB I'll probably deploy Postgres on AWS and install some scripts to back up the data to an S3 bucket every day or so.

I chose NOT to use k8s or Docker because, like you said, it's basically a fulltime job to maintain. I don't think it's needed at all unless you're a large organization.

So basically: a mixture of roll-your-own, streamlining platforms, and hosted services. Do whatever works and is easiest, and don't worry so much about having ALL the goodies.

I run my own Heroku clone which is then licensed by my other companies.

Also, I review how much time each product / feature consumed each year and then decide what to deprecate. Each April I then have my own little party where I ceremoniously turn off last year's time wasters.

I'd say it all boils down to "know your customer lifetime value"

Ex-Googler here and 20+ year veteran of SF startups.

It sounds like you have a great set of intuitions, and you're right, all that infrastructure is a nightmare to set up and manage.

Step 1: Question every requirement

Step 2: Drop everything that is not critical

Step 3: Profit!

Git hooks and Makefiles are great!

I have an HP workstation I bought from eBay under my desk that has 32GB of RAM, 2x 12 core CPUs and a static IP address. It's probably 8 years old, but fast enough to serve whatever we need for a long while.

The machine (Old Blue), hosts our Git repos, web app, database and integration service (git hook that calls, 'make publish').

We're not serving Google scale traffic, so we don't need Google scale infrastructure.

Keep it simple whenever possible and don't let the modern stack complexity creep in until you absolutely need it.

Even going to the cloud, when you've done it 10 times and know how, is way more work than you need when just starting out.

Take on those costs and complexities only when your traffic requires it, and you may just find out that you never have to pay rent for compute.

I hope you’re backing up customer data if you store any…
Definitely.

In fact, it's super easy to back up as it's in a SQLite database (for now).

How do you backup the SQLite?

I used to rsync them, but when traffic picked up, I started to fear an inconsistent copy (rsync does verify at the end there are no new changes, and restarts - but i don’t know the exact strategy so I am wear if relying on it).

I switched to doing .backup and rsync that instead - but am considering switching to litestream instead.

I had a K8s setup running on Google cloud, using their managed database service. This was kind of nice, but expensive, cost ~$100 a month, and I was using very low specs.

I have multiple projects, none of them making money currently, so $100/month for each basic app is not good.

I switched to using Dokku on Vultr, $12 a month. You can easily create Postgres databases and link them to Docker apps. I haven't bothered to setup CD yet but it looks like it should be simple, for now I just push to it when I want to deploy. Liking this setup so far.

For frontend I use Netlify, I use their redirects to proxy the backend.

Not a solo founder, but I do a lot of ops professionally. Unless you have a specific reason, I say it’s best to avoid complicated tooling until later.

k8s, ci, etc are all really useful and solve a lot of hard problems, but god are they a bitch to set up and then monitor, fix when something weird happens, secure from nasty people outside, patch when some update becomes necessary, resist the urge to “improve”, etc. This doesn’t include the time it takes to work these tools into your project, like k8s for example really requires you grok its model of how stuff it runs is supposed to look. There’s a reason entire companies exist that simply offer managed versions of these services!

If you’re using fewer than like 10 boxes and don’t work with many people, you can get away with spooky arcane oldhat sysadmin deploy techniques (scp release to prod hosts, run deploy script, service or cron to keep running) and honestly it’s pretty fun to just run a command and poof you’re deployed. Then you can just wait until it starts making sense to use fancier tooling (more load, more sites/DCs, more services, more people/teams, etc). Monitoring is always good to start with, for other stuff a good litmus test is that price points for hosted k8s & ops stuff will start to make sense, you’ll be paying in time in any case. Who knows, maybe when that happens something new will pop up that makes even more sense. Until then, reducing the amount of stuff you need to worry about is always a good strategy.

Agree with all of this.

If you want an intermediate step you can just make docker images of your application and deploy and run those manually (again with shell scripts).

You can get a long way that way without having to deal with kubernetes.

> If you’re using fewer than like 10 boxes and don’t work with many people, you can get away with spooky arcane oldhat sysadmin deploy techniques (scp release to prod hosts, run deploy script, service or cron to keep running)

If you have multiple people on the team that have access to servers, this will shoot you in the foot a year or two later. Good luck replicating that server setup when no one has any clue whatsoever about all the small tweaks that were performed ad-hoc over the years.

Next step up is something like Ansible to manage it all.
Yes. Then you realize that people may still SSH into your servers and manually tweak things when they need the fix "now". So then you start restricting SSH access and forcing everything through Ansible. And now you're deep in deployment best practices again ;)
I think you’re describing the growing pains that justify paying the costs of more complicated tooling. The big difference is that instead of needing to figure it out as a solo founder with bigger problems, in this scenario you get to figure it out as a solo founder with a team and presumably some extra $$.
> Good luck replicating that server setup

It is easy when the server is regularly backuped.

> spooky arcane oldhat sysadmin deploy techniques (scp release to prod hosts, run deploy script

I never realised I was using spooky arcane oldhat stuff! I feel wizardly now.

My projects (for small clients and myself) basically use this.

- A "build.sh" script that does a local build of back end and front end

- A "deploy.sh" script that scp's everything to the server (either a digital ocean VPS or an EC2 instance), runs npm install, runs database migrations and restarts with pm2

So running my entire CI pipeline in terminal is: ./build.sh && ./deploy.sh

Basically same here. In cases the deployment has to be zipped and manually deployed to elastic beanstalk. On some EC2 instances for projects running a PHP stack, I don't even bother with this, just SFTP script changes to the server straight out of my IDE. Take care of any rollback needs with local Git versioning.
This is great. Until you need to roll back.
Keep a simple tool like Ansible around for those spooky admin tricks and you can take advantage of the Ansistrano plugins for smooth deploy and rollback (Ruby's great Capistrano tool ported to Ansible).

https://ansistrano.com/

It's pretty fantastic.

This looks awesome. I'm currently in the middle of learning Ansible now for my FjeeBSD jails. Have any other plugins to recommend?
Anything by geerlingguy on Ansible Galaxy.
> Anything by geerlingguy on Ansible Galaxy.

I've been writing some Ansible playbooks recently for the first time in years, and came upon geerlingguy's work. That guy is a powerhouse when it comes to writing Ansible roles/modules!

Why? Checkout what version you want to roll back to, and deploy it.

    git checkout abcd1234
    ./build.sh && ./deploy.sh

I don't see the issue.
If you have any migration, you probably want to rollback them as well
That's sort of pet peeve of mine: Migration are done separate from code deploys. Version 1 of your code runs on schema version 1. Schema version 2 does not make chances that will break code version 1. Code version 2 can utilize the chances made in schema version 2, but you're still able to rollback the code.

Each schema migration should also come with its own rollback script.

The downside is that you might need three migrations for some operation, but at least you won't break stuff.

The assumption that you can do a schema migration while deploying new code is only valid when you have very limited database sizes. I've seen Flyway migrations break so many times, because developers assumed it was fine to just do complicated migrations on a 200GB database. Or a Django database migration just lock up everything for hours because no one cared to think about the difference between migrating 100MB and 100GB. And I've never seen anyone seriously considering rolling back a Flyway migration.

Agree with this and have practiced and advocated for it. Make the schema changes to support the new feature first, then verify existing software still works. Deploy the schema change. Then develop the new feature, test, and deploy the program. That way you can deploy and rollback without needing to synchronously run a bunch of migration routines.
I had a similar setup a couple of years ago, where I had to deploy without downtime. My solution was to simply have the old version running in parallel until I was certain the new version was ok

----------

Static website:

1. Setup NginX using a symlink to the current version

2. Copy the new files to a separate folder

3. Change the symlink to point to the new version

----------

REST service (behind NgninX reverse proxy):

1. Current version runs on port X.

2. Deploy new version and run it on port Y.

3. Update NginX config to use port Y and reload

4. If you need rollback, just reverse step 3.

This can be done using scripts or Ansible too if necessary.

My favorite deploy is using a simple `git pull` instead of scp. I also avoid complex build tools when I can. You either need your built files in the repo or you need to avoid them. Either are fine for my small personal projects. The only real exception I make is keeping any necessary secrets out of my repo. Those get dropped on the server manually.

This also solves the roll-back problem mentioned elsewhere. Just checkout the previous version (as long as you don't make any side effects like DB updates that are incompatible).

I admit, this requires relatively simple software.

I do the same thing (just a couple os customers, o en Linode per customer). Hopefully I'll need something more complex eventually.
Why pull, as opposed to push(ing to the server as remote)?

Then you could have any necessary restart or migration or whatever run in a post-receive hook.

I realise that's starting to get back in to tooling and config etc., but it's not that complex, and if you're already using git anyway...

Naive question: what's the correct way of doing this when you need to cp your content to a dir like /var/www/html that your user doesn't own (when logging in as root is prohibited)? My "spooky" (and probably very stupid) method is an Expect script that lets me supply a password to sudo.
Usually these directories are owned by another group (www or www-data) so that your web server program (nginx, apache, etc) can access them without running as root. If you add your user to that group, you should be able to manage files in your web root without sudo. Be careful with permissions, though - you may need to chown to set the group after copying so that the files are readable by your web server.
Ideally you want some atomic deployment strategy, rather than having to deal with whatever crap might have been in the directory previously. Something like - extract your deployment artefact to a new, unique directory - and then read-only bind-mount that directory as /var/www/html.

> and probably very stupid) method is an Expect script that lets me supply a password to sudo.

The old school sysadmin way of doing this would be to have a dedicated deployment user (ssh pubkey auth only - possibly restricting only specific commands), with a sudoers[.d] configuration to allow that user to run an explicit group commands without a password (NOPASSWD)

a pattern I have seen before is to clone the branch commit of each release to a folder /var/releases/{release_commit} and then html is not a folder but a soft link so /var/www/html -> /var/releases/latest_release_commit this is useful if you need to revert back quickly. But then releases folder needs to be cleaned up, or you can run out of space.
That's dangerous unless you've properly configured your web server to block access to your .git directory.
Safer/easier to keep the .git somewhere else entirely, rather than in the working directory. Git's got arguments that let you do that. Then you can check out to a dir that doesn't have the .git dir in it at all.

Alternatively, it's pretty easy to use git-archive (optionally, with an exclusions list to keep out files you don't want to serve publicly) to do something similar without ever cloning the remote repo. You can fetch a zip or tar.gz with a given commit's files, straight from a remote repo.

Login as the user that owns that dir, don't try to hack around the user permissions.

Also you probably don't want your web under /var if its a partition and you fill it with lets say user content then you will lock up your server.

Ansible can do this (you tell it the user to initially log in, and that you need to "become" another user for a task)
If you like this style of deployment, and you haven't looked into Ansible yet, give it a try, you may enjoy it. I had similar build processes before using Ansible and I have found it a really positive step up.
This is a great setup if you work with a lot of clients. Every client we work with wants everything to run on their infrastructure that they provide, and then they provide the weirdest jankiest setup you could imagine. Because of this I keep everything basic if it cant run on a fresh linux install or less (looking at you docker) then its going to cause issues down the line.
rsync and scp are two of my top favorite commands.
Indeed, for a bunch of hobby things, I use

   rsync -rvzC --no-p --no-g --chmod=ugo=rwX --stats -e "ssh . ${remote}:${path}"
where `${remote}` is defined in `.ssh/config` and `${path}` is in the project config to move files over to a new deployment directory. Then, a quick command over SSH changes the symlink to the site's configuration file and restarts the web server.

The sites are either on Linode or SSDNodes. Has been working for me for decades and don't need to change it for these hobby things. After all, the log files prove that these things get more traffic from exploitation probes than real people ;-)

Also a hobbyist sysadmin at home, but after reading a few comments on the internet, I found that the rsync -z compress flag was bottlenecked on a maxed-out CPU thread of my Raspberry Pi 4 NAS transfers.

Admittedly, these are mostly "local" drive-to-drive transfers over USB rather than server-to-server transfers over house-wide gigabit. But consider trying the transfer without compression.

I'll definitely have to read up on your other flags though, if your rsync works from just one machine rather than both that might solve a minor problem case I have where the destination machine lacks rsync...

https://unix.stackexchange.com/questions/188737/does-compres...

Really good observation. All the settings are from a long time ago when link quality was way worse than what we get these days.

I should review those options, definitely.

> -C, --cvs-exclude auto-ignore files in the same way CVS does

Just goes to show you how long I've been using this stuff :-)

The additional options may not be relevant now that I am just deploying creating a new target directory each time.

Or just deploy it on Heroku and call it a day?
yah, this (or something similar) is the most straightforward solution. the whole point of heroku is to abstract away devops for solo/small dev groups and make deployments “one-click”. it’s unclear why that option was explicitly ruled out here.
I'm fully on team spooky admin - however on my latest project, I've been loving being on the free tier of tools like vercel, which deploys from git commit, and firebase, which is mostly maintenance free. That really reduces the amount of devops in my day.
>you can get away with spooky arcane oldhat sysadmin deploy techniques (scp release to prod hosts, run deploy script, service or cron to keep running)

You would be surprised at how many old enterprises still do this. Sure, it's ugly, but it can be simpler than k8s, and anyone with scripting chops can understand it.

At this point CI is pretty easy to setup and monitor and it's integrated with practically every development/deployment tool, so I have to disagree about waiting to implement it.
Yeesh

I cannot imagine not setting up at least a basic CI. Even if you remove all unit/integration test alarms, a CI is still very useful. The 20 minutes of build -> upload -> deploy script -> check prod vs a 1/2 day to set up a CI and forget it.

I'm not sure you save much time but you save a lot of headache

I think you mean automation is very useful. I've worked in a lot of places where we had a single `make deploy` that could compile, test, upload the artifacts, deploy the artifacts to hosts, start the new services, and slowly transition the load balancer to point at the new instances while automatically backing out if error metrics started lighting up. This is just automation, it doesn't have to happen on every commit. Especially when working solo or on a small team, I might not want to maintain a lot of VCS branches and instead, just deploy when I feel it's ready. You have to do all of that stuff anyway, so if you later decide to hook it up to a VCS trigger, you're all set.
I guess that's fair, I'm probably coming into this having only seen it done a certain way and blind to other possibilities.

That being said, it would take a lot to convince me a standard CI/CD pipeline is not worth the investment. My only experience with non CI/CD deployment process was a very manual process at a startup, then when I saw my first CI/CD it felt like magic.

A good old makefile is a CI/CD pipeline. All the new fangled tools are re-inventing a lot of capabilities make already has. I blame the new kids on the block who have only ever known Windows :-)
I only have side-projects, very different from a full-time, revenue earning solo-preneur, but I only use serverless. My preferred stack now is NextJS, hosted on Vercel with FaunaDB. The main reason is to “outsource” devops to them.

I am not sure how it would work on a larger scale, but for my use is perfect.

How much money do you spend on this?
Right now, zero, as I am using only free tiers. But my understanding is that it is expensive when you scale.

Vercel first paid plan is $20/month and FaunaDB $25/month, so my guess is a business with some traction would have to pay at least these $45/month.

Unpopular answer alert, but it worked well for my context for the few years before I hired a team.

I didn’t do CI/CD. I just reviewed my own code the next day, improved it and put it live. As the only dev I knew more or less how my code worked and what risk factors to prepare for in each deploy, and serious, business-impacting production issues were rare.

A simple stack of Meteor on Galaxy + Mongo on Atlas meant all my tools integrated well together and a whole lot of devops things were easy enough that I rarely had to think about them after they were set up once.

I can think of many cases where this would not work but it worked well for my context.

Don't use them. They require time to maintain and if you are old like me half of them make very little sense anyway.
If the hours you spend implementing and maintaining your DevOps exceed the hours of downtime you prevent, you're probably not making good use of your time. The less you build, the less you have to maintain.

I've been running a Python-based, highly custom web store solo since 2007, and it supports multiple people doing fulfillment. I host on Opalstack so as to outsourcing patching, email config, database maintainence, etc. I run directly in a Git repo (actually Hg, it's that old) and releases are "git pull && ./restart.sh". Rollbacks are "git checkout ...".

I've had to migrate/rebuild the VM about every 5 years. Tech changes enough in that time that no automation will still work unmodified. So I just keep good notes about what I did last time, and figure out what the new equivalents are when I finally have to do it again (updating the notes, of course). Database and Conda are easy to port. It's usually DNS and email integrations that are a pain.

As others have said, KISS is key. Industry DevOps is for a work setting with a decent-sized team, where you can afford the overhead of maintaining it all in order to make the overall team more efficient.

Pieter Levels (the guy who made Nomad List) reached $1 000 000 ARR with a single VPS, all his code in an index.php file and using FTP to transfer the latest code to his server...

I think if you’re a solo founder you have to accept on day one you’re at a time disadvantage when it comes to the actual hours you’ll spend on moving the business forward vs admin, ops, legal stuff etc etc and so you have to really fight smart!

I.e K8S? Definitely don’t need it. Complex CI/Deployment workflow? Nope, just the minimal shell scripts to do clean deploys and rollbacks. Pay for a HA RDS so you never need to worry about DB replication etc.

If you just work with the minimal set of tools you’re comfortable with and relentlessly keep things simple it’s possible. I’ve built high availability stuff as a solo founder and still found (at least some...) time to work on sales and the business.

I think you are right. There's a big difference between the technology I would use in a larger organization compared to solo projects.

Unless you build a side project to learn a new technology, you should use something "boring" that you know well.

Here's my personal choices in preferred order:

1. Static web sites - Just upload to S3 behind a CDN and forget about it

2. Server rendered website - PHP. It may not be something you brag about, but in my experience it just "works" and has excellent uptime.

Note: If I had to recommend something to a larger organization, I would probably suggest Next.js to attract developers. PHP is often associated with "old school" tech

3. REST service - Spring Boot. I have so much experience with it and there are so many Spring projects that supports a huge range of technologies from monitoring to data

4. Scripts - Python

What is a HA RDS?
High Availability Relational Data Store

An example would be AWS' RDS

High-availability relational data store.
I have been working on https://quantale.io since a year and half. It's a web based alternative to Bloomberg Terminal.

I personally manage the CI/CD infra as well as the data infrastructure for my startup.

Here is my setup:

1. Self-hosted Drone.io instance connected to github(the instance is behind a firewall and can only be accessed via a self-hosted VPN. Github IPs are whitelisted so that auto build/deployment can be initiated via github hooks)

I have drone.io config that helps me manange the versioning, deployment to stage/production, run tests, do rollbacks etc.

for eg: merging to master on github auto builds the master branch on drone and deploys to staging along with pulling the latest db backup from S3 and adding to stage for testing

2. Self-hosted production and staging server that hosts my web/django app. It has a local postgres db and is encrypted and backed up on S3 every hour.

3. Self-hosted Elasticsearch cluster using Ansible playbooks with daily snapshot backups to S3.

beyond this, I self-host 3 VPNs to protect my entire infrastructure. read my old HN comment about it: https://news.ycombinator.com/item?id=28671753

All this is one time infrastructure setup and it all has been running smoothly for more than a year without any hiccups.

I would be happy to help you setup a similar setup if you want. hit me up at vikash@quantale.io

> 2. Self-hosted production and staging server that hosts my web/django app. It has a local postgres db and is encrypted and backed up on S3 every hour.

Did you have any instance where you needed to restore the DB / Have you done restoration tests to ensure this is a feasible solution? Also, since you are using local postgres DB, do you not run into issues like transaction id wraparound ?

Also, how many days of backup you keep on S3? Considering you create 24 backups a day.

> Did you have any instance where you needed to restore the DB / Have you done restoration tests to ensure this is a feasible solution?

Whenever a build is deployed to stage server, it automatically pulls the latest version backup in last 1 hour and restores it on the stage for testing with the latest data. I have config to do the same restore to the prod if needed.

I have been using the same setup for over 2 years to support an internal web app of a company.

> Also, since you are using local postgres DB, do you not run into issues like transaction id wraparound ?

This problem only arises when there is heavy load on the database, specifically high WRITE/UPDATE/DELETE operations. Quantale uses postgres to store only user info and all the other data is stored in Elasticsearch(twitter, reddit, news, SEC, Financial data on over 15000+ stocks). This is intentional because with the scalable server resources, my postgres setup can handle a large number of users before I see that problem. I can always scale up later when needed rather than over-engineering it right now.

>Also, how many days of backup you keep on S3? Considering you create 24 backups a day.

I have 7 days backups on S3 with versioning switched on for 60 days. So at anytime I can access the version backed up in last 60 days.

scottydelta, Thank you for taking the time to give me more context / insight.

Safe to say you have a verified way of backup and restore (with worst case data loss of an 1 hour).

I am not exactly an expert on what stage does Transaction ID Wraparound comes in but still know that as one of the key criticisms of PostgreSQL so wanted to check.

Also, 7 days backup with versioning switched is a smart tactic! Thanks once again for this.

This seems to (strangely) be an unpopular answer here, but I've spent a weekend to terraform everything. I run a couple of different projects which are yet to pick-up traction, so prototyping quickly is essential.

What I have now is terraform on Github which handles Networking (VPC, subnets), ECS/ECR, ALB for my backend and S3/CloudFront for frontend.

Everything is on AWS because I'm familiar with it, so it's faster. And I compensate for costs with AWS Activate + Free Tier. This combination is usually enough to understand whether the project will get traction or not.

Actually spending little time on IaC was one of the best recent investments. But I guess it holds more value when you have a couple of projects, still exploring and these tasks get repetitive

I find this helpful for my side project as well. It's amazing how quickly a) things break down and b) I forget how to set things up and get running again if I have to shelve and restart work on a project.
I spent a lot of time on Terraform + Packer code to set up VPC, RDS, Route53, AWS Cert Manager, ELB, EC2, my API server, S3, CloudFront, and CloudWatch. The setup had a lot of complexity and footguns. Plus there was the risk of accidentally running up a huge AWS bill.

Later, I realized that Heroku + Netlify are good enough. Switching was easy. The hardest part was admitting to myself that I had wasted so much time on AWS. I felt relieved after I deleted the Terraform and Packer code.

AWS bill is a concern. I put alerts on billing but they do come with a delay.

I was thinking Digital Ocean. Or Heroku for the current project, but ended up with a design with quite a few serverless pieces using lambda. Which has a great free tier and is very useful for my use-case.

Would not say that AWS is too much complexity though.. When you go over things at least once and understand how thing fall together

Lots and lots of best practice exists specifically to help teams, and especially teams with some normal amount of turnover.

The problems of a solo dev are very different than a dev on a team. Knowledge silos don't exist. Distributed expertise doesn't exist. There's no one to mentor, no shared vision to maintain, no intertia to combat.

I consult on big complicated team projects. I also manage multiple solo projects.

On solo projects, deployment is a script I run from my dev machine. I'm the only person who deploys; anything else would be solving a problem I don't have.

The only "CI" is running the tests before I run the deployment script. I'm the only one who needs to see the outcome of the tests. Anything more would be solving a problem I don't have.

Architecture is whatever makes the most sense to me personally -- which is often miles away from what I would recommend to a client, who needs something any new hire will recognize and be able to work with.

I pay a service to manage backups so I can walk away from a solo project for months and know it's ticking away.

The point is: solve problems you actually have. Don't try to run a "professional" operation by doing what big teams do all by yourself. Big teams have different problems.

Totally agree with this. I do big corp work and the problem space is totally different from what is needed for a single developer.
> I pay a service to manage backups so I can walk away from a solo project for months and know it's ticking away.

Any recommendation of such service?

Borgbase. I'm not affiliated with them, I'm just a happy customer
Pretty much anyone you can pay to host a database, you can pay to back it up. Amazon rds, heroku postgres, google cloud sql... pick the service that works for you, and they have some affordance for backups. Backups are something I expect, rather than something I shop around for.
My experience says to backup to a different vendor.
This is part of my threat model. Is there an easy way to do this with e.g. hosted RDS or block storage device snapshots?
In my case I'm dumping + zipping the entire database at the application level. In my case is as simple as adding a library [1], scheduling the job and transferring to AWS S3 (my main application is on DigitalOcean)

[1] https://github.com/spatie/laravel-backup

'knowledge silos' in a one person team are real: Me today and me from 2 years ago when I set a thing up are different people, and I don't remember that any more than a team mate in a multi-person team would know it. This is where 'professional' approaches can help considerably: using 'standardized' stuff, instead of bespoking everything (even if bespoking is much easier), or making sure you write a TON of documentation for anything you don't do daily...
I'm a fan of the documenting everything even on stuff I wrote and maintain for myself. Because, like you said, old me was way smarter than current me. When he was writing this code, he had the domain space modeled in his head better than me now, 2 years later trying to fix/maintain something.
Probably the best tool you have is somewhere to write your notes down. What you did, why you did it, how to reproduce it. That saves you time in a year or two when you go 'hmm I did something like this before have to do it again because some CPU ate itself'. My old notes have saved me a lot of re-work over the years. Because I had written down what I did so I do not have to rebuild it. I can just skip along the notes and be most of the way there.

This bit seems to hold true across any size team for me. If I have notes I can spiffy them up and make cheat sheets out of them and bootstrap other developers faster. Or if it is just me, my feeble brain will forget odd details that I needed for something.

https://fly.io

- Easy Postgres clusters (but not managed) - Heroku like deploys (but less magic) - Easily geodistributed (deploy near your users) - reasonable pricing to get started (and not too bad beyond that).

I do all like this:

GiHub actions-> docker build->docker push to github package repo

then on vm a 2 line script to docker pull && docker-compose up -d

Database all by hand.

Extremely easy i just push, wait build and restart

I'm not a solo-preneurs, but I have some open-source projects (mainly a live one, and one that I'm currently developping).

Here are the list of DevOpss flow I've done:

* One project is a website. I have a pipeline, triggered when something is merged to master, that builds Docker images, pushes them to a Dokku instance and deploy them.

* One project is a JS library. I have a pipeline, triggered when a git tag is created, that packages the library and uploads it to npm. I use Netlify to host the documentation website of it.

* For this same project, I'm planning to have a pipeline triggered for each PR to run the linter and tests.

I work as a DevOps/MLOps, and I'm quite comfortable with CI tools in general. I hate doing things manually and I love automating, so it comes quite naturally for me to do it. Once it's set up, it rarely needs to be changed.

Not a solo-preneur, but I’ve had great experiences so far with Dokku, an open-source Heroku clone. I’m running ~40 apps on my single VPS since a couple of years. I use it in combination with Github Actions, Bitbucket Pipelines and Gitlab CI. I still feel very flexible working with Dockerfiles and different cloud services. I’ve only had to update the dokku-letsencrypt plugin a couple of times in the past 5 years. Note that I haven’t had to protect important databases with PII for example.
I'm starting to consider this myself and have been looking at https://serverless-stack.com/#guide as a way to prototype and build an MVP. The guide has quite a bit in it that I believe can be repurposed to that end although it doesn't cover backups etc, more integrations with AWS services.
Yup it's meant to be a starting point for projects of all sizes. We built our own stuff using it as well. Feel free to reach out if you have any questions. Or join us on Slack: https://launchpass.com/serverless-stack

Good luck!

I have no idea why there's nothing here saying "don't". Go and get a Heroku account, hook it up to your Github repository's master branch for deploys, use Github Actions for CI, and then get on with life.

Yes, you'll pay more for a Heroku Postgres instance than you would for a VPS on Digital Ocean with Postgres running on it, likewise you'll pay more for Heroku Dynos than another VPS to run your application server. On the other side though, your backup, rollback, deploy, and scaling strategies can all be "Heroku does that", and you can focus on the much more valuable job of building a business.

This! Plus it includes SSL provisioning, staging environments, background workers etc.

Other competitors like render.com are starting to look like they'll be competitive on features and are way cheaper too.

Yep! Used Heroku at a previous gig (now a mid-size startup), worked great, now on Render.com and it's also great. Also factor in fly.io and railway as quickly-growing platforms in the same PaaS sort of space.
I head up Dev Advocacy at Render (previously at Heroku). Happy to answer any questions about Render.
I'm really only waiting on PITR for postgres before moving all my workloads over to render. Do you know when that will be available?
(Render CEO) We're targeting early next year, but it might be sooner if we can hire faster!
Exactly. And when you are truly "beyond POC level and beyond heroku (for whatever reason)" then of course it is time to hire people.

I see this all the time. Entrepreneurs trying to solve the people problem by avoidance. The problem with the super efficient player is twofold. First, it's not really scaleable. Second, what if the person gets sick or is in vacation?

I really like Heroku, when I work on NodeJS projects.

BUT: In the last year I've had some rather serious downtime issues that were 100% Heroku's fault. (Poor encapsulation of Postgres configuration via the connection string, and they mistakenly claimed that I violated their TOS when I didn't. They apologized and fixed the situation.)

I'd really like to see some good alternatives to Heroku. Not just because of their screwups, but because the languages that I want to work on have limited support in Heroku.

which languages do you want to work on?
C# and Rust.

Edit: Yes, I know there are community supported ways to do this, But I want something that is as slick as the NodeJS ecosystem on Heroku.

Heroku Postgres – after all those years – still is vulnerable to MITM attacks. You can't reliably verify the authenticity of the connection between Heroku's Dyno and the Postgres database.

They use self-signed certificates on Heroku Postgres servers without a certificate authority present in the chain. No chance to establish reliable peer verification. A shame, I would love to use Heroku more often without compromising security.

+1. For pre-A series/pre-revenue/pre-1k paying customers and other early stage businesses you can do a lot worse than starting out on Heroku, especially if you don't have sysadmin/cloud/devops expertise (and even if you do, that time could/should be spent on much more important things at this stage).
Until Heroku has a huge downtime (like recently) and you are f*ked. If you have your own VMs, you can quickly move them to a different provider, but it's hard to start figuring out servers when Heroku is down and your business stopped.

That said, I would also recommend Heroku to many.

I can almost guarantee that over a period of years you'll see significantly less downtime that can be attributed to Heroku than you would on VMs that you manage. Even if that isn't the case, if Heroku are responsible for it then you can mostly just kick back and let them fix it, rather than spending 24 hours without sleep migrating VMs between providers.

The context here is also that of a single entrepreneur building a business. At that point in the lifecycle of a product downtime really isn't that big of a deal, customers tend to be pretty understanding so long as you recover.

Anyone who kicks back while their web hosting is down... is a psychopath. That's just not going to happen. Are you accountable to literally nobody? Even as a solopreneur, there are customers/visitors. If my site is down, I am losing money/credibility/visitors/etc. Sure, you will probably get past it, but it means preparing to communicate to those people during/after. It also means understanding what went wrong and what could be done to prevent it. Just kick back and not worry about it sounds like you're doing nothing of consequence to anyone.
Heroku is by far the best for this but just to throw in some alternatives:

  * Digital Ocean Apps -- somewhat finicky but works very similar to Heroku, it gets closer to bare metal so I prefer it
  * render.com
  * AWS Elastic Beanstalk -- though setting this up is non-trivial, it is very similar to Heroku with its "set it and forget it"
  * AWS Container Services -- if you're using Docker
  * Google App Engine
  * Supabase -- geared for SPAs but this may be the ticket depending on what you're building, is open source

You may want to use your own VPS but spend for a managed database solution as this has the most potential for catastrophe.
Also AWS Copilot if you like CLI based tooling, similar to Elastic Beanstalk but easier (at least if you're comfortable making a Dockerfile)
Was not aware of Copilot! Looks much better than Elastic Beanstalk
I would advise against Elastic Beanstalk, last time I used it the product had the stink of being on life support - they've not really added any new features to it in several years, and even before that it was incredibly flakey.
What additional features are you looking for? I've been using beanstalk for the past few years, and just wrapped up doing a large deployment on it. I've never found beanstalk to be a bottleneck or not have a feature I was looking for.
I use Elastic Beanstalk daily it is maintained and supports everything on AWS, they've added ALB and WAP for example. It runs on Cloud Formation. Never experienced anything "flakey"
A concur. I got burned three times by Elastic Beanstalk in 2019 before switching away.

1. Their server manager process got in an unresponsive state. It wouldn't update my service. It stopped reporting logs from the service that was running. I went to the AWS Loft and consulted with the AWS Support technician. They had me log into the machine with SSH and troubleshoot. I was using Elastic Beanstalk specifically so I would not have to log into machines.

2. The console frequently showed servers as running when they weren't. And vice-versa. I wasted a lot of time trying to figure out why my server didn't start when it actually did start and why my server isn't listening on its port when the console incorrectly showed that it started. Logs were also delayed randomly.

3. The final straw happened on a Saturday. Elastic Beanstalk suddenly started returning errors. I purchased an AWS Support subscription and filed a ticket. It turns out Elastic Beanstalk Team had deployed on a Saturday and then rolled back. Unfortunately, anyone who did API calls through the new API version got new values added to their Elastic Beanstalk API backing database. The rolled-back the server errored when it saw the new values. They refused to just fix the bad data in their database caused by their bad deployment. Instead, they asked me (their customer) to download special management tools and perform manual operations to fix it. And I had to pay them to find out these instructions.

Now I use Heroku.

Recently Beanstalk got upgraded to their "Amazon Linux 2" making it basically pretty much a Heroku clone, you even set up Procfile and services ;-) It still requires a LOT of hacking and insider-knowledge to do some funkier things, but it's a great thing
Add TinyStacks to this list. They are just getting going, but I got a demo recently - sort of a cross between Vercel and Heroku, but on AWS.
Does SPA stand for Single Page Application?
I think so. You'd use it as the backend for your SPA:

> Create a backend

But you'd probably host your SPA elsewhere, eg Vercel, Netlify, GitHub pages

Totally agree. There's some impostor syndrome in play here. If you don't need the scale, why waste your time managing a more complex setup? Heroku might be slightly more expensive in the short term but your time is better spent building/selling than future-proofing or just doing it because larger operations have to.
I'd even go higher up the value chain with something like Vercel or Netlify if your stack fits in their offering. Heroku is a definitely a good option if you need more flexibility. The costs won't be a bottleneck until you actually have enough scale that you can afford DevOps staff.
Vercel has the best dev UX in my opinion, everything just "works" the way you expected it the first time, and if not their documentation is very straight forward.
This is what I've been doing for years, but Heroku Postgres is so bloody expensive, it just doesn't make sense for apps that don't make much money. So I just moved my data to an RDS instance, shared between multiple apps. Cost savings are great, headache savings much less so. I would say if you are going to move off Heroku, do it with the apps/projects where you can f-up, or have downtime without much repercussion. AWS stuff is a deep dark forest, undocumented and confusing. I'd say for anything that is critical, just keep paying Heroku. It isn't worth it.
Are you actually doing this for a production app with income you rely on? Because Heroku has horrendous uptime these days. Lot's of random emergencies on both worker and web dynos. Don't forget you share routing with thousands of other apps too so expect random hiccups there too. It's easy to give this advice but does not scale well with complexity.