Serverless Functions Development for Websites (Google Cloud Functions)
Google Cloud Functions (2nd gen) — serverless functions based on Cloud Run. Unlike 1st gen, 2nd gen supports up to 60 minutes execution, multiple concurrent requests per instance, and a wider choice of runtimes: Node.js, Python, Go, Java, .NET, Ruby, PHP.
First Generation vs Second Generation
2nd gen functions use Cloud Run under the hood. This provides: concurrency up to 1000 requests per instance (vs 1 in 1st gen), VPC Connector support, larger memory limits (32 GB), custom domains without proxying.
Function Example: Webhook Processing
import functions_framework
import json
import hmac
import hashlib
from google.cloud import pubsub_v1
publisher = pubsub_v1.PublisherClient()
TOPIC_PATH = "projects/my-project/topics/webhook-events"
@functions_framework.http
def process_webhook(request):
# Signature verification
signature = request.headers.get("X-Signature-256", "")
secret = get_secret("webhook-secret")
expected = "sha256=" + hmac.new(
secret.encode(), request.data, hashlib.sha256
).hexdigest()
if not hmac.compare_digest(signature, expected):
return json.dumps({"error": "Invalid signature"}), 401, {"Content-Type": "application/json"}
event = request.get_json()
# Publish to Pub/Sub for async processing
publisher.publish(TOPIC_PATH, json.dumps(event).encode("utf-8"))
return json.dumps({"received": True}), 200, {"Content-Type": "application/json"}
Node.js Function with TypeScript
import { http, HttpFunction } from "@google-cloud/functions-framework";
import { SecretManagerServiceClient } from "@google-cloud/secret-manager";
const secretClient = new SecretManagerServiceClient();
const contactForm: HttpFunction = async (req, res) => {
res.set("Access-Control-Allow-Origin", "https://your-site.com");
if (req.method === "OPTIONS") {
res.set("Access-Control-Allow-Methods", "POST");
res.set("Access-Control-Allow-Headers", "Content-Type");
res.status(204).send("");
return;
}
if (req.method !== "POST") {
res.status(405).json({ error: "Method not allowed" });
return;
}
const { name, email, message } = req.body;
// Get API key from Secret Manager
const [version] = await secretClient.accessSecretVersion({
name: "projects/my-project/secrets/sendgrid-api-key/versions/latest"
});
const apiKey = version.payload?.data?.toString();
await sendEmail({ name, email, message, apiKey });
res.json({ ok: true });
};
http("contactForm", contactForm);
Deployment
# Node.js
gcloud functions deploy contact-form \
--gen2 \
--runtime nodejs20 \
--region europe-west1 \
--source . \
--entry-point contactForm \
--trigger-http \
--allow-unauthenticated \
--memory 256MB \
--timeout 30s
# Python
gcloud functions deploy process-webhook \
--gen2 \
--runtime python312 \
--region europe-west1 \
--source . \
--entry-point process_webhook \
--trigger-http \
--memory 512MB
Environment Variables
gcloud functions deploy my-function \
--set-env-vars DATABASE_URL=postgresql://...,NODE_ENV=production
# Or via Secret Manager (recommended for secrets)
gcloud functions deploy my-function \
--set-secrets 'API_KEY=my-secret:latest'
Pub/Sub Subscriber Function
@functions_framework.cloud_event
def process_pubsub_message(cloud_event):
import base64
data = base64.b64decode(cloud_event.data["message"]["data"]).decode("utf-8")
event = json.loads(data)
# Event processing: CRM sync, notification, etc.
handle_event(event)
Runs automatically when a message is published to the Pub/Sub topic.
Cloud SQL Connection
For PostgreSQL/MySQL use Cloud SQL Auth Proxy via Unix socket — not TCP:
import sqlalchemy
def create_engine():
return sqlalchemy.create_engine(
f"postgresql+pg8000://user:pass@/dbname",
creator=lambda: pg8000.connect(
user="user",
password="pass",
database="dbname",
unix_sock="/cloudsql/project:region:instance/.s.PGSQL.5432"
)
)
In Cloud Run (and Cloud Functions 2nd gen) Cloud SQL Auth Proxy runs as a sidecar automatically when you specify --add-cloudsql-instances.
CI/CD via Cloud Build
# cloudbuild.yaml
steps:
- name: node:20
entrypoint: npm
args: [install]
- name: node:20
entrypoint: npm
args: [run, build]
- name: gcr.io/google.com/cloudsdktool/cloud-sdk
args:
- gcloud
- functions
- deploy
- contact-form
- --gen2
- --region=europe-west1
- --source=.
- --runtime=nodejs20
- --entry-point=contactForm
- --trigger-http
Timeframe
Basic functions with deployment and environment variables — 2–3 days. Pub/Sub integration and Cloud SQL — plus 2 days.







