Splitting production/development databases - node.js

I'm working on a mongoDB backed expressjs app. I've used the express generator to create it.
I would really like to work on a development database through MongoLab, and then deploy to Heroku (which would also be backed by a MongoLab database).
What are the best practices for splitting these two up so when I start the app in development mode it uses the development mongo instance, and when I deploy to heroku in production mode it will use the production DB?
Thanks!

Heroku's 12Factor architecture document does a great job of explaining both the best practices of config management, and the rationale behind them:
http://12factor.net/config
The tldr is, "pull in config from environment variables and use explicit configuration instead of named environments like 'development' or 'production.'"
Heroku will provide all the environment variables you need for connecting to your mongolab db, so all you have to sort out is providing those same variables to your app locally. One common solution is the .env file:
https://devcenter.heroku.com/articles/heroku-local#copy-heroku-config-vars-to-your-local-env-file
This is essentially a file that you don't check in, which provides a list of key-value pairs for your local environment variables. It can be run through Heroku Local or, more generally, via tools like node-foreman or docker-compose.
disclosure: I'm the Node.js platform owner at Heroku

Related

Heroku wont work with my Keyv and Sqlite database

Ive made a database from sqlite and i uploaded that with my github to Heroku but its only getting the data from the database and not changing it. No errors, just not working. When i am testing it on my pc it works fine.
I'm not sure why you're only able to get data and not change it. If you can share an example of how you're getting and setting, I might be able to help you get it going temporarily.
I learned, however, that SQLite only offers temporary storage on Heroku:
Why is SQLite a bad fit for running on Heroku?
Disk backed storage
SQLite runs in memory, and backs up its data store in files on disk. While this strategy works well for development, Heroku’s Cedar stack has an ephemeral filesystem. You can write to it, and you can read from it, but the contents will be cleared periodically. If you were to use SQLite on Heroku, you would lose your entire database at least once every 24 hours.
Even if Heroku’s disks were persistent running SQLite would still not be a good fit. Since SQLite does not run as a service, each dyno would run a separate running copy. Each of these copies need their own disk backed store. This would mean that each dyno powering your app would have a different set of data since the disks are not synchronized.
Instead of using SQLite on Heroku you can configure your app to run on Postgres.
I then followed their instructions for setting up Postgre. It's worth reading through the instructions, but the gist of it to use the Heroku CLI:
From the section Provisioning Heroku Postgres:
"Use the heroku addons command to determine whether your app already has Heroku Postgres provisioned"
If heroku-postgresql doesn’t appear in your app’s list of add-ons, you can provision it with the following CLI command: heroku addons:create heroku-postgresql:hobby-dev
As of writing, the hobby tier is free. Read about plans here.
This command adds an environment variable to your project named DATABASE_URL.
I'm using keyv by Luke Childs. I installed its companion #keyv/postgres. (I also uninstalled my sqlite stuff.)
I used the newly added DATABASE_URL environment variable to wire into the keyv steps linked above:
const Keyv = require('keyv');
const keyv =
process.env.NODE_ENV !== "production"
? new Keyv()
: new Keyv(process.env.DATABASE_URL);
I haven't found the best solution yet for developing/testing Postgre locally. Heroku Postgre requires SSL for connecting remotely (when your app is running locally). In the code block above, you'll see that I'm initializing Keyv without a database while developing locally (new Keyv()).
From here, if I need to verify the DB storage, I can set up a PostgreDB for developing locally, but I also imagine that it's possible to connect to the Heroku Postgre using SSL. If you or anyone has a solution they like for this step, please let me know.
#T. Rotzooi, I'm three months late to your question, but perhaps this explanation could help future people. I haven't found any other resources discussing this issue that you and I both encountered.

How to run and start mongodb from within nodejs

Basically I don't want to use an existing mongodb database site like the official mongocloud or whatever-- how can I do what they do, but myself? Do I just include the database folder, along with all of the mongodb executable, in my nodejs folder and call require("child_process").spawn("mongodb.exe", /insert params here/), or is there some kind of way to do this in the mongo module?
And also do I need my own virtual machine to be able to do this or can the following work on a standard heroku nodejs application for example?
Anyone?
Heroku's hosting solution has only ephemeral volumes, so you can't use it for a database. Any files you create are temporary and will be purged on a regular basis.
For example, when your application is idle Heroku will de-provision that resource and clear out any data you've left there.
You can't use Heroku like this, you must use an external database service, or one of their many add-on offerings.

Deploy node.js in production

What are the best practices for deploying a nodejs application in production?
I would like to know how deploy for production Api's nodejs is being done today, today my application is in docker and running locally.
I wonder if I should use a Nginx inside the container and deploy my server on it or just upload my image node that is already running today.
*I need load balance
There are few main types of deployment that are popular today.
Using platform as a service like Heroku
Using a VPS like AWS, Digital Ocean etc.
Using a dedicated server
This list is in the order of growing difficulty and control. So it's easiest with PaaS but you get more control with a dedicated server - thought it gets significantly more difficult, especially when you need to scale out and build clusters.
See this answer for more details on how to install Node on a VPS or a dedicated server:
how to run node js on dedicated server?
I can only add from experience on AWS using a NAT Gateway which is a dedicated Node server with a MongoDB server behind the gateway. (Obviously this is a scalable system and project.)
With or without Docker, you need to control the production environment. This means clearly defining which NPM libraries you will need for production, how you handle environment variables and clusters for cores.
I would suggest, very strongly, using a tool like PM2 to handle clusters, server shutdowns and restarts and logs. (Workers & slaves also if you need them and code for them).
This list can go on and on, but keep in mind this is only from an AWS perspective. Setting up a Gateway correctly on AWS is also not an easy process. Be prepared for some gotcha's along the way.

Different database for production and development in nodejs

I know that Ruby on Rails has this feature, and in the railstutorial it specifically encourages it. However, I have not found such a thing in nodejs. If I want to run Sqlite3 on my machine so I can have easy to use database access, but postgres in production on Heroku, how would I do this in Nodejs? I can't see to find any tutorials on it.
Thank you!
EDIT: I meant to include Node.JS + Express.
It's possible of course, but be aware that this is probably a bad idea: http://12factor.net/dev-prod-parity
If you don't want to go through the hassle of setting up postgres locally, you could instead use a free postgres plan on Heroku and connect to it from your local machine:
DATABASE_URL=url node server.j
A .env file can make this easier:
https://devcenter.heroku.com/articles/heroku-local#copy-heroku-config-vars-to-your-local-env-file
To switch between production and development Db you use different ports for running you application locally and on Heroku.
As Heroku by default runs the application to port 80 you have a some other port while running your app locally.
This will help you to figure out in run time if your application is running locally or in production and you can switch the Databases accordingly.
You could use something like jugglingdb to do this:
JugglingDB(3) is cross-db ORM for nodejs, providing common interface to access most popular database formats. Currently supported are: mysql, sqlite3, postgres, couchdb, mongodb, redis, neo4j and js-memory-storage (yep, self-written engine for test-usage only). You can add your favorite database adapter, checkout one of the existing adapters to learn how, it's super-easy, I guarantee.
Jugglingdb also works on client-side (using WebService and Memory adapters), which allows to write rich client-side apps talking to server using JSON API.
I personally haven't used it, but having a common API to access all your database instances would make it super simple to use one locally and one in production - you could wire up some location detection without too much trouble as well and have it automatically select the target db depending on the environment it's in.

Digitalocean: cross droplet communication

I have a scenario with two nodejs apps deployed on two Dokku droplets. One of my apps is three admin app which stores data to a mongodb database. The other app is the main application which reads data from that database.
How can I make this main app communicate to the database?
You need to link the database to the dokku container via environment variables. You basically need to follow this methodology: http://12factor.net/
The database needs to be accessible via an IP and port combination on one of your two servers. If you need both servers to communicate with the database then you will need to make sure it is externally accessible and properly secured (for example via a VPN).
You can then set an environment variable like so:
dokku config:set DB_URL='mongo://10.0.0.1:4192/database_name'
obviously changing the above to match your setup.
Another potentially easier way of doing the above is to use a dokku plugin which will basically automate those steps.
A list of plugins is available at: http://progrium.viewdocs.io/dokku/plugins
There is a mongo plugin which may suit your needs, I've used some of the others and they work well.

Resources