How to deploy Node.js app to Google Cloud Functions
Google Cloud Functions provides serverless compute platform for running Node.js code in response to HTTP requests or cloud events without managing servers. As the creator of CoreUI, a widely used open-source UI library, I’ve deployed serverless Node.js functions to Google Cloud throughout my 11 years of backend development. The most straightforward approach is using Functions Framework locally for development and gcloud CLI for deployment to Google Cloud. This method enables rapid serverless deployment, automatic scaling based on traffic, and cost-effective pay-per-invocation billing model.
Install Functions Framework, create HTTP function, and deploy using gcloud CLI for serverless Node.js execution.
# Install Functions Framework for local development
npm install @google-cloud/functions-framework
Create HTTP function:
// index.js - Simple HTTP function
const functions = require('@google-cloud/functions-framework')
// Register HTTP function
functions.http('helloWorld', (req, res) => {
const name = req.query.name || req.body.name || 'World'
res.status(200).send(`Hello, ${name}!`)
})
More complex example with Express-style routing:
// index.js - API with multiple endpoints
const functions = require('@google-cloud/functions-framework')
// User data (in production, use Firestore or Cloud SQL)
const users = new Map([
['1', { id: '1', name: 'Alice', email: '[email protected]' }],
['2', { id: '2', name: 'Bob', email: '[email protected]' }]
])
// Main HTTP function
functions.http('api', (req, res) => {
// CORS headers
res.set('Access-Control-Allow-Origin', '*')
res.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE')
res.set('Access-Control-Allow-Headers', 'Content-Type')
// Handle preflight
if (req.method === 'OPTIONS') {
res.status(204).send('')
return
}
// Route handling
const path = req.path || '/'
const method = req.method
try {
if (path === '/' && method === 'GET') {
res.json({ message: 'API is running' })
} else if (path === '/users' && method === 'GET') {
const userArray = Array.from(users.values())
res.json({ users: userArray })
} else if (path.startsWith('/users/') && method === 'GET') {
const id = path.split('/')[2]
const user = users.get(id)
if (user) {
res.json({ user })
} else {
res.status(404).json({ error: 'User not found' })
}
} else if (path === '/users' && method === 'POST') {
const { name, email } = req.body
const id = String(users.size + 1)
const newUser = { id, name, email }
users.set(id, newUser)
res.status(201).json({ user: newUser })
} else {
res.status(404).json({ error: 'Not found' })
}
} catch (error) {
console.error('Error:', error)
res.status(500).json({ error: 'Internal server error' })
}
})
Background event function:
// index.js - Cloud Storage trigger
const functions = require('@google-cloud/functions-framework')
const { Storage } = require('@google-cloud/storage')
const storage = new Storage()
// Triggered when file uploaded to Cloud Storage
functions.cloudEvent('processFile', async (cloudEvent) => {
const file = cloudEvent.data
console.log(`Processing file: ${file.name}`)
console.log(`Bucket: ${file.bucket}`)
console.log(`Size: ${file.size} bytes`)
console.log(`Content type: ${file.contentType}`)
// Process file (e.g., generate thumbnail, analyze content)
try {
const bucket = storage.bucket(file.bucket)
const fileRef = bucket.file(file.name)
const [metadata] = await fileRef.getMetadata()
console.log('File metadata:', metadata)
// Perform processing
if (file.contentType.startsWith('image/')) {
console.log('Processing image...')
// Image processing logic
}
} catch (error) {
console.error('Error processing file:', error)
throw error
}
})
Package configuration:
{
"name": "my-cloud-function",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"start": "functions-framework --target=api --port=8080",
"deploy": "gcloud functions deploy api --runtime nodejs20 --trigger-http --allow-unauthenticated"
},
"dependencies": {
"@google-cloud/functions-framework": "^3.3.0",
"@google-cloud/storage": "^7.7.0"
},
"engines": {
"node": ">=20.0.0"
}
}
Local development:
# Start function locally
npm start
# Test with curl
curl http://localhost:8080
curl http://localhost:8080/users
curl -X POST http://localhost:8080/users \
-H "Content-Type: application/json" \
-d '{"name":"Charlie","email":"[email protected]"}'
Deployment with gcloud CLI:
# Install gcloud CLI (if not already installed)
# Visit: https://cloud.google.com/sdk/docs/install
# Initialize gcloud
gcloud init
# Set project
gcloud config set project YOUR_PROJECT_ID
# Deploy HTTP function
gcloud functions deploy api \
--runtime nodejs20 \
--trigger-http \
--allow-unauthenticated \
--entry-point api \
--region us-central1 \
--memory 256MB \
--timeout 60s
# Deploy with environment variables
gcloud functions deploy api \
--runtime nodejs20 \
--trigger-http \
--allow-unauthenticated \
--set-env-vars DATABASE_URL=your-db-url,API_KEY=your-key
# Deploy Cloud Storage trigger function
gcloud functions deploy processFile \
--runtime nodejs20 \
--trigger-event google.storage.object.finalize \
--trigger-resource YOUR_BUCKET_NAME
# View deployment info
gcloud functions describe api
# View logs
gcloud functions logs read api --limit 50
# Test deployed function
curl https://REGION-PROJECT_ID.cloudfunctions.net/api
Advanced configuration with separate config file:
# .gcloudignore - Files to exclude from deployment
.gcloudignore
.git
.gitignore
node_modules
test/
*.test.js
.env
README.md
Environment-specific deployment:
# Production deployment
gcloud functions deploy api \
--runtime nodejs20 \
--trigger-http \
--allow-unauthenticated \
--region us-central1 \
--memory 512MB \
--timeout 60s \
--max-instances 100 \
--set-env-vars NODE_ENV=production
# Development deployment
gcloud functions deploy api-dev \
--runtime nodejs20 \
--trigger-http \
--allow-unauthenticated \
--region us-central1 \
--memory 256MB \
--set-env-vars NODE_ENV=development
Monitoring and debugging:
# View logs in real-time
gcloud functions logs read api --limit 50 --follow
# Get function details
gcloud functions describe api --region us-central1
# Delete function
gcloud functions delete api --region us-central1
# List all functions
gcloud functions list
Here the Functions Framework provides local development environment matching Cloud Functions runtime. The functions.http registers HTTP-triggered functions accepting request and response objects. The cloudEvent function handles background events from Cloud Storage, Pub/Sub, or other triggers. The gcloud CLI deploys functions with runtime specification, trigger configuration, and resource limits. Environment variables pass configuration without hardcoding secrets. The –allow-unauthenticated flag enables public HTTP access without authentication. Memory and timeout limits control resource usage and costs.
Best Practice Note:
This is the serverless deployment strategy we use for CoreUI microservices requiring automatic scaling without infrastructure management on Google Cloud Platform. Keep functions focused on single responsibility with cold start times under 1 second, use Cloud Secret Manager for sensitive configuration instead of environment variables, implement structured logging with Cloud Logging for production monitoring, and leverage Cloud CDN with Cloud Functions for globally distributed low-latency API endpoints.



