ANR's Blog
Published on

Serverless Hit Counter Using Node JS and postgresql on lambda


In this blog post we will see how we can make and add a hit counter that runs on a node js serverless architecture and uses postgresql as database hosted on aws lambda.

Database Setup

I will be using a postgresql database hosted on supabase.

In our database we will have a hits table with two columns slug and hits.

Slug will be the url of the page and hits will be the number of hits for that page.

Slug will be the primary key of type text and hits will be of type int4.

I think a signed four byte int will suffice for most people as it's range is -2,147,483,648 to 2,147,483,647 but if it is not enough for you. you can use a signed eight byte int as it's range is -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807.

Node JS project Setup

Initiate a new node js project using the command npm init and install the following packages:

npm i --save express
npm i --save dotenv
npm i --save @supabase/supabase-js
npm i --save serverless-http

add type="module" to the package.json file.

Express makes it easy to create a server that handles incoming requests and sends responses.

dotenv is a module that loads environment variables from a .env file into process.env.

@supabase/supabase-js is a module that makes it easy to connect to a supabase postgres database.

serverless-http module allows us to wrap our express server for use with serverless.

Inside the index.js file paste the following code:

import dotenv from 'dotenv'

import express from 'express'
import { createClient } from '@supabase/supabase-js'
import serverless from 'serverless-http'

const app = express()
const port = process.env.PORT || 3000
const supabaseUrl = process.env.SUPABASE_URL
const supabaseKey = process.env.SUPABASE_KEY
const supabase = createClient(supabaseUrl, supabaseKey)

app.get('/', function (req, res) {
  res.send('Hi there! How are you?')

app.get('/register-hit', async function (req, res) {
  const slug = req.query.slug
  if (!slug) {
    res.send('No slug provided')
  let hits = 1
  const { data, error } = await supabase.from('hits').select('hits').eq('id', slug)
  if (error) {
    console.log('Error getting hits: ', error)
  if (data && data.length > 0) {
    hits = data[0].hits + 1
    const { updateData, updateError } = await supabase
      .update({ hits: hits })
      .eq('id', slug)
    if (updateError) {
      console.log('Error updating hits: ', updateError)
  } else {
    const { insertData, insertError } = await supabase.from('hits').insert({ id: slug, hits: 1 })
    if (insertError) {
      console.log('Error inserting hits: ', insertError)
  res.send({ hits: hits })

app.listen(port, function () {
  console.log('register hits app listening on port ' + port)

export const handler = serverless(app)

or if you want you can clone the project from github using the command

git clone -b lambda

Lambda Setup

In your aws console go to lambda dashboard and click on create function.

Give your function a name and select node js as runtime.

Click on Advanced Settings and select Enable function URL.

Select None for auth type and Enable Configure cross-origin resource sharing (CORS).

Click on create function.

Upload your project to aws lambda

Create a zip file of your project or download the zip file from github release and upload it to aws lambda by clicking on upload from button in the top right corner of the lambda dashboard and select the zip file.

Now click the settings icon in the Environment section of code source and select Show hidden files.

Change the values in the .env file to match your database credentials and the url of your project.

Now Deploy your project to aws lambda by clicking on deploy.

You should see your project deployed on aws lambda.

you can test your project by visiting the url of your project in your browser.

We have successfully deployed our node js hit counter project to aws lambda.

You can see see the hit counter working in production on Study-Site.

You can also configure the cross origin resource sharing (CORS) to allow only your site to access the api by going to the configuration tab of your lambda function and then to Function URL and click on edit.

Now you can add your domain name to the allowed origins.

By default the allowed origins are set to * which means that any domain can access the api.