Hacker News new | comments | ask | show | jobs | submit login

Go and, honestly, sqlite with backups written to S3. It's the absolute cheapest. I can run multiple apps on a t2.nano (t2.micro if I am feeling fancy). My apps cost something like $1.50 to run a month, and they can easily handle medium-sized traffic, plus Go is just so dead simple to deploy. scp a build binary, and boom I am done. Once the app grows and more collaboration/developers/requirements call for it, I will add more infrastructure.

I (and I imagine many people on HN) would be extremely interested in some sort of basic guide to your process.

Sure, I don't have anything formal written up, but I think this might make a good topic for my first blog post. It really isn't complicated though in all honestly. I primarily stick to the stdlib, use a go sql driver for sqlite, I used to just run s3 sync on a cron but I am experimenting doing it in code now with the go aws lib, and just a couple bash scripts to "deploy" (I mean, really, it's go build, scp, and a webpack build + s3 upload for the frontend when that's needed. Go and sqlite really does most of the work here in terms of keeping things light and small.

My most complicated build required somewhat of an SOA approach, but rather than go heavy-duty microservices and use grpc where you need a bunch of load balancing and service discovery involved, I went with something simple called nats, that ended up costing me 5 dollars a month, unfortunately.

Thanks for sharing your setup here. Go and SQLite are great! I have a few questions :-)

Is the Go service directly accessible from Internet, or is it hosted behind a reverse proxy?

When you deploy a new binary, is there a small downtime between stopping the old binary and starting the new one?

How do you supervise the Go process? You use something like systemd?

When SQLite backup is ongoing, does it block writes to the database?

When you backup to S3, if an attacker gets control of your EC2 instance, is he able to erase your S3 backups, or is it configured in some kind of append-only mode?

Where do you store your logs and do you "read" them?

These are fantastic questions and id love to hear the answers.

I will answer my own questions, in the context of the apps I develop and maintain:

- The Go service is hosted behind a reverse proxy (nginx or haproxy) to enable zero downtime deployments, by 1) starting the new process, 2) directing new requests to the new process, and 3) gracefully stopping the old process.

- Since we've started to use Docker, we let the Docker daemon supervise and restart our services. Before Docker, we used systemd. Before systemd was available on our system, we used supervisord.

- We thought about using SQLite for some apps. But SQLite can only have a single writer at a time, which goes against the zero downtime deployment described above (two processes can be processing requests at the same time). Thus we use PostgreSQL (and MySQL for legacy reasons) which provides online backups. Must be noted that online backups are possible with SQLite, provided the application implement it using SQLite Online Backup API [1]. Another solution, which doesn't require application cooperation, is to snapshot your disk, if your system supports this.

- We backup to rsync.net, which provides an append-only mode, through their snapshot feature [2]. An attacked cannot override or erase the snapshots of your previous backups. I think it's possible to do something similar with S3, albeit in a bit more cumbersome way, using S3 versioning and MFA deletion.

- About logs, we're still not satisfied by what we use currently.

I'd be curious to read about what others do :-)

[1] https://www.sqlite.org/backup.html

[2] https://www.rsync.net/resources/howto/snapshots.html

I agree. Golang binaries are great to work with on cloud instances. And they are basically designed to run forever ;)


Do you use a framework? Do you do everything server side with Go or do you have a JS library on the front-end?

net/http and REST api all the way down, I for the most part try to stick to the stdlib as much as possible. The few exceptions are logging (I like zerolog) the sql driver, and auth. I do keep the front/backend separation because doing site hosting in S3 with a cloudfront cache is pennies on the dollar (.63 cents a month) and I tend to lean towards using vue.js more these days. I have been known to just serve the html statically directly from go as well, and use go templates in the past, and use minimal jquery where it's needed (I still like jquery :-/, not everything needs to be full-blown SPA-mode)

I've recently decided to drop javascript frontends for a hobby project of mine and just go with bare go templates. Someone hopefully will laugh at it, but it has been a great, productive decision. It's been easy and quick again to slap ugly lists or tables of stuff together.

The entire headache of choosing a web framework, generating a seed of magnificient complexity, wrestling with the javascript build ecosystem, figuring out how to balance state between JS ui components, JS state management, backend state management and databases. Not necessary. Do an SQL query, put that into a neat datastructure and run html templating, followed by <go build>. Maybe add bootstrap for some neat CSS.

What Go libraries do you use?

Mainly the stdlib, see above answer. Exceptions are logging auth, and sql driver.

Which one do you use for auth? Any recommendations?

Applications are open for YC Summer 2019

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact