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
- 
                 Go to the Google Cloud Console. 
- 
                 Select your project. 
- 
                 In the left nav, go to Firestore → Create Database. 
- 
                 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
|  | 
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:
- 
                 Go to IAM & Admin. 
- 
                 Find the default App Engine service account. 
- 
                 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
CS651