CS651 | Web Systems
  • outline
  • projects
  • syllabus
  • links

 

 

How to use Cloud Firestore (Datastore mode) with Node.js in Google App Engine:

 

 


Native Mode vs Datastore Mode

Step Firestore Native Mode Firestore in Datastore Mode
SDK used firebase-admin @google-cloud/datastore
Data model Document/Collection (hierarchical) Entity/Kind (flat, relational-like)
Real-time support ✅ Yes ❌ No
GAE integration ✅ Native support ✅ Native support

 

 

 

Step 1:Set Firestore to Datastore Mode

  1. Go to the Google Cloud Console.

  2. Select your project.

  3. In the left nav, go to Firestore → Create Database.

  4. Choose Datastore mode, select a location (cannot be changed later), and create it.


Step 2: Create Your Node.js GAE App

File structure example:

my-app/
├── package.json
├── app.js
└── app.yaml

Step 3: Add Firestore SDK

In your project folder, run:


npm install @google-cloud/datastore

Step 4: Initialize Firestore in app.js & use it (here saving)

>>>NOTE: credentials and permission is setup in console --see at the bottom of this page

const express = require('express');
const { Datastore } = require('@google-cloud/datastore');

const app = express();

// Creates a Datastore client using Application Default Credentials
const datastore = new Datastore();

app.get('/', async (req, res) => {
  const kind = 'Message';
  const taskKey = datastore.key([kind]);

  const entity = {
    key: taskKey,
    data: {
      text: 'Hello from GAE and Firestore in Datastore Mode!',
      timestamp: new Date(),
    },
  };

  try {
    // Save the entity
    await datastore.save(entity);

    // Query latest 5 messages
    const query = datastore
      .createQuery(kind)
      .order('timestamp', { descending: true })
      .limit(5);

    const [messages] = await datastore.runQuery(query);

    res.send(messages);
  } catch (error) {
    console.error('Datastore error:', error);
    res.status(500).send('Error accessing Datastore');
  }
});

const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
  console.log(`App listening on port ${PORT}`);
});

 

 

Code Snippet to read/retrieve from Datastore

const { Datastore } = require('@google-cloud/datastore');

// Initialize Datastore client (uses Application Default Credentials on GAE)
const datastore = new Datastore();

// Function to retrieve latest messages
async function getLatestMessages(limit = 5) {
  const query = datastore
    .createQuery('Message')
    .order('timestamp', { descending: true })
    .limit(limit);

  try {
    const [messages] = await datastore.runQuery(query);
    return messages;
  } catch (error) {
    console.error('Error retrieving messages from Datastore:', error);
    throw error;
  }
}
 


Step 5: Create app.yaml for GAE Standard


runtime: nodejs20  # or nodejs18
instance_class: F1

env_variables:
  GOOGLE_NODE_RUNFILES: "1"

note:

instance_class: F1

This controls the size and cost of each App Engine instance. It's optional, but important if you want to manage performance and billing.

Instance Class Memory CPU Free Tier Eligible?
F1 256 MB 600 MHz ✅ Yes
F2 512 MB 1.2 GHz ✅ Yes
F4 1 GB 2.4 GHz ❌ No
  • F1 is the smallest, cheapest, and free-tier eligible (ideal for testing or small traffic).

What is GOOGLE_NODE_RUNFILES: "1"?

This is a special GAE setting used with Node.js apps. It tells App Engine to include node_modules binaries and runtime files when packaging your app.

  • It’s helpful for compatibility and ensures that dependencies (especially those that rely on compiled binaries like firebase-admin) run properly.

  • Without this, certain modules may behave unexpectedly in some edge cases.

You usually don’t need to touch this unless troubleshooting issues — but including it is safe and ensures maximum compatibility.

 

 


Step 6: Deploy to GAE

Make sure you're authenticated with Google Cloud SDK:

gcloud auth login
gcloud config set project [YOUR_PROJECT_ID]  
gcloud app deploy  

Visit your app after deployment:

gcloud app browse  

Step 7 – Verify IAM Permissions

By default, GAE uses this service account:

[PROJECT_ID]@appspot.gserviceaccount.com

Make sure it has at least the Cloud Datastore User role:

  1. Go to IAM & Admin.

  2. Find the default App Engine service account.

  3. Ensure it has one of these roles:

    • Cloud Datastore User (recommended)

    • Editor (for full access during development)

 

 

NOTE:

 

What Does await Do in JavaScript?

await is a keyword in JavaScript that can only be used inside an async function. It tells the program to wait for a Promise to complete before continuing.

 

const result = await someAsyncFunction();

 

  • someAsyncFunction() returns a Promise.

  • await pauses execution of the current async function until the Promise is resolved (success) or rejected (error).

  • The resolved value gets stored in result.

  • If the Promise is rejected, the error can be caught using try...catch.

 

cs651:web systems

  • home
  • outline
  • projects
  • syllabus
  • links