visit
The intent of this article is not to do a deep dive on building a Node.js microservice application. However, if you have some experience with Node.js, TypeScript, Express, and PostgreSQL, you’ll likely find additional value in the code presented here.
Our mini-demo application is a user management API with several typical endpoints for retrieving, creating, updating, or deleting users. Behind the scenes, the service performs query operations on the PostgreSQL database. You can find the complete application code here.
We’ll start with the PostgreSQL instance since we’ll need database credentials before we can use our Users service. To create an instance for your project, log in to and click the New + button in the top right corner. Then, click on PostgreSQL to start the process. This drops you into a form to configure your database:
Specify a name for your instance, along with a database name and user name for access. For the “Datadog API Key” field, it’s important to add this now because it’s difficult to add it after the database has been created. Paste in the API key that you generated from the previous step.
Click Create Database and wait for the initialization to complete. Render will display the credentials for your new database. You’ll need those later when setting up your Users’ service.
Note also that we’ll need to initialize the schema in this new database, creating a user table with proper columns. We’ll do this via the node-pg-migrate
package. The instructions for initializing the database are in the code repository’s file. However, we’ll bundle this step into our application’s startup command on Render.
Deploying a microservice with Render is straightforward, especially if you host your code in or . After you connect your code hosting account to Render, return to your Render dashboard. Click on the New + button and select Web Service. Select the code repository with your microservice.
Node
.yarn install && yarn build
so that all the dependencies are installed and the final system is built.yarn migrate up --no-reject-unauthorized && yarn start:prod
DB_HOST
DB_NAME
DB_USER
DB_PASSWORD
DATABASE_URL
— This is the database connection string used by node-pg-migrate
. Its value is postgres://DB_USER:DB_PASSWORD@DB_HOST:5432/DB_NAME
, with the actual values for these placeholders filled in. For example: postgres://john:[email protected]:5432/mydb
Lastly, make sure to set the “Health Check Path” to /health
to facilitate zero-downtime deploys and health monitoring within Render.
Click Create Web Service. Render will work its magic and deploy this service from your repository!
Log into your Datadog account and navigate to the Metrics page.
The top line of the Metrics Explorer shows the metric query toolbar with various dropdown and input boxes for filtering what metrics are displayed in the graph. The default metric, system.cpu.user
is shown. If your database was configured correctly with the API key, then you should see a line graph displaying the percentage of time the CPU spent running user space processes.
If you want to investigate a different metric, select the first input box and enter system.mem
. The auto-complete will show different memory-related metrics:
If you select system.mem.used
, you’ll start to see the database host’s memory that is in use. Notice that the dialog provides a description of the selected metric.
In this query, the “from” field uses the single-database instance, and Datadog sums the data based on the database-id
property on the metric.
Fortunately, Datadog provides significant resources for alerting upon an occurrence of poor performance currently happening with your systems. You can configure these alerts to monitor the metrics that you choose, pushing notifications to various places.
Select Monitors from the Datadog navigation bar, and then select New Monitor and choose the Metric monitor type.
Select Threshold Alert and then define the metric query just as you would on the metrics page. We want to use the postgres.connections
metric from our single database instance. Lastly, we select the min by threshold. If the “minimum number of connections” is above a threshold, this indicates that there are currently too many connections on this database instance. That’s when we should be alerted.
This is a contrived example, but it means that Datadog will trigger a warning if it detects 12 connections to the database over the past five minutes. Meanwhile, we’ll receive a full alert on 20 connections to the database over the past five minutes.
Next, let’s look at how to use logs to understand what is happening inside of the system itself.
In Node.js development, using console.log
is a common debugging technique. Seeing log output is easy when you’ve deployed your Node.js application to your local machine, but it’s challenging if you’ve deployed it to the cloud. This is where help.
To set up syslog export, log into your Render account and go to your Account Settings page. Click on Log Streams. Add the endpoint for your log aggregator, along with an API token (if any). For our example, we’ll send our syslogs to Datadog.
In Datadog, navigate to the Logs tab.
This brings you to the Log Search dashboard where you can see a live tail of all the logs being ingested by your Datadog account. This includes logs emitted by our database instance, our Node.js microservice, and the Render build process for our microservice.
Logs emitted from the application via console.log
or a logger such as Pino will show up here, aiding in the debugging effort. You can trace entire requests through your systems by following them through your various services logs. As data flows through your system from your API endpoints to the service layer and then to the database layer, you can use logs to track down the root cause of issues.
catch
block, you can do more than just handle the exception; emit a log message with helpful contextual information. Then, query for these kinds of messages in your log management system to track down the root cause.log
. When using , you’re not limited to just using console.log
. You can also use functions like console.info
, console.debug
, and console.error
. Doing so will help you differentiate the severity of what you’re logging, making it easier to query or filter for specific issues.200
, 401
, and 500
), then you can set up an alert to notify you when a certain response code is seen too frequently. You could set up an alert to tell you when a 500
or a 401
code has been seen more than five times in ten minutes, indicating a possible issue that needs to be dealt with immediately.