Skip to main content
S-Parking backend services are deployed as containerized Node.js 20 microservices on Google Cloud Run, Google’s fully managed serverless compute platform. This guide covers the deployment process for all backend functions.

Architecture Overview

The S-Parking backend consists of multiple independent Cloud Run services:
  • ingest-parking-data - Receives IoT sensor data from ESP32 devices
  • get-parking-status - Returns real-time parking spot status
  • reserve-parking-spot - Handles spot reservations
  • release-parking-spot - Releases reserved spots
  • create-parking-spot - Creates new parking spots
  • delete-parking-spot - Deletes parking spots
  • manage-zones - Zone management operations
  • get-zones - Retrieves zone information
  • get-occupancy-history - Returns historical occupancy data
  • save-hourly-snapshot - Triggered by Cloud Scheduler for analytics

Prerequisites

1

Install Google Cloud SDK

Download and install the gcloud CLI:
curl https://sdk.cloud.google.com | bash
exec -l $SHELL
2

Authenticate with Google Cloud

gcloud auth login
gcloud config set project YOUR_PROJECT_ID
3

Enable Required APIs

gcloud services enable cloudbuild.googleapis.com
gcloud services enable run.googleapis.com
gcloud services enable firestore.googleapis.com

Build Container Images

Cloud Run requires containerized applications. Use Google Cloud Build to create Docker images:

Single Function Build

# Navigate to function directory
cd web-dashboard/gcp-functions/services_ingest-parking-data_*

# Build and push image to Google Container Registry
gcloud builds submit --tag gcr.io/YOUR_PROJECT_ID/ingest-parking-data

Batch Build All Functions

# Build all Cloud Functions
for dir in web-dashboard/gcp-functions/*/; do
  FUNCTION_NAME=$(basename "$dir" | sed 's/_function-source$//' | sed 's/services_//' | sed 's/_[0-9.]*$//')
  echo "Building $FUNCTION_NAME..."
  gcloud builds submit "$dir" --tag gcr.io/YOUR_PROJECT_ID/$FUNCTION_NAME
done
Each function directory must contain a valid Dockerfile or package.json for Cloud Build to process. S-Parking uses the Node.js 20 buildpack automatically.

Deploy to Cloud Run

Deploy Individual Service

gcloud run deploy ingest-parking-data \
  --image gcr.io/YOUR_PROJECT_ID/ingest-parking-data \
  --platform managed \
  --region us-central1 \
  --allow-unauthenticated \
  --memory 256Mi \
  --cpu 1 \
  --max-instances 10 \
  --set-env-vars FIRESTORE_COLLECTION=parking_spots

Deployment Parameters Explained

ParameterPurposeS-Parking Value
--platform managedUse fully managed Cloud RunAlways set
--allow-unauthenticatedAllow public access (required for IoT devices)Set for IoT endpoints
--memoryContainer memory allocation256Mi (sufficient for lightweight functions)
--cpuCPU allocation1 (auto-scales under load)
--max-instancesMaximum concurrent instances5-10 based on expected traffic
--timeoutRequest timeout60s default, 300s for long operations
The ingest-parking-data endpoint must be publicly accessible (--allow-unauthenticated) for ESP32 devices to send sensor data. Implement API key validation in the function code if security is a concern.

Environment Variables

Set environment variables during deployment:
gcloud run deploy YOUR_SERVICE_NAME \
  --image gcr.io/YOUR_PROJECT_ID/YOUR_SERVICE_NAME \
  --set-env-vars \
    FIRESTORE_COLLECTION=parking_spots,\
    NODE_ENV=production,\
    LOG_LEVEL=info

Common Environment Variables

  • FIRESTORE_COLLECTION - Firestore collection name (default: parking_spots)
  • NODE_ENV - Runtime environment (production or development)
  • LOG_LEVEL - Logging verbosity (info, debug, error)

Verify Deployment

After deployment, test your Cloud Run service:
# Get service URL
gcloud run services describe ingest-parking-data \
  --platform managed \
  --region us-central1 \
  --format 'value(status.url)'

# Test endpoint
curl https://YOUR_SERVICE_URL.run.app

Check Logs

# View real-time logs
gcloud run logs tail ingest-parking-data --project YOUR_PROJECT_ID

# View recent logs
gcloud run logs read ingest-parking-data --limit 50

Update Existing Service

To deploy a new version:
1

Rebuild Image

gcloud builds submit --tag gcr.io/YOUR_PROJECT_ID/ingest-parking-data
2

Deploy New Revision

gcloud run deploy ingest-parking-data \
  --image gcr.io/YOUR_PROJECT_ID/ingest-parking-data \
  --platform managed \
  --region us-central1
Cloud Run automatically handles zero-downtime deployment.
3

Verify Revision

gcloud run revisions list --service ingest-parking-data

Configure Cloud Scheduler

For time-based functions like save-hourly-snapshot, set up Cloud Scheduler:
# Create hourly snapshot job
gcloud scheduler jobs create http save-hourly-snapshot-job \
  --schedule "0 * * * *" \
  --uri "https://save-hourly-snapshot-[HASH].run.app" \
  --http-method POST \
  --oidc-service-account-email YOUR_SERVICE_ACCOUNT@YOUR_PROJECT.iam.gserviceaccount.com
The cron expression "0 * * * *" triggers the function every hour at minute 0. Adjust based on your analytics requirements.

Troubleshooting

Issue: “Service not found”

Solution: Verify the service was deployed to the correct region:
gcloud run services list --platform managed

Issue: “Container failed to start”

Solution: Check function dependencies in package.json:
{
  "dependencies": {
    "@google-cloud/functions-framework": "^3.0.0",
    "@google-cloud/firestore": "^7.0.0"
  }
}
Ensure all required packages are listed.

Issue: “Permission denied” errors

Solution: Grant Cloud Run service account Firestore access:
gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \
  --member serviceAccount:YOUR_SERVICE_ACCOUNT@YOUR_PROJECT.iam.gserviceaccount.com \
  --role roles/datastore.user

Issue: High cold start latency

Solution: Set minimum instances:
gcloud run deploy ingest-parking-data \
  --min-instances 1 \
  --image gcr.io/YOUR_PROJECT_ID/ingest-parking-data
Minimum instances incur continuous costs. Only use for critical, latency-sensitive endpoints like IoT data ingestion.

Cost Optimization

S-Parking’s Cloud Run deployment is cost-optimized:
  • Memory: 256Mi (minimum for Node.js functions)
  • Auto-scaling: Scales to zero when idle
  • Request timeout: 60s (prevents runaway charges)
  • Max instances: Capped at 10 to prevent billing spikes

Monitor Costs

# View Cloud Run metrics
gcloud run services describe ingest-parking-data \
  --format 'value(status.traffic)'
Use Google Cloud Console → Cloud Run → Metrics to monitor request counts, latency, and instance usage.

Next Steps

Configure Frontend

Deploy the web dashboard to Firebase Hosting

Flash ESP32 Firmware

Program IoT sensors with Cloud Run endpoint URLs

Environment Configuration

Set up API URLs and secrets management

Build docs developers (and LLMs) love