| name | azure-patterns |
| description | Azure Functions, Cosmos DB modeling, Service Bus patterns, Bicep templates |
Azure Patterns
Azure Functions
HTTP Trigger (Node.js v4)
import { app, HttpRequest, HttpResponseInit, InvocationContext } from '@azure/functions';
app.http('getOrder', {
methods: ['GET'],
authLevel: 'function',
route: 'orders/{orderId}',
handler: async (request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> => {
const orderId = request.params.orderId;
context.log(`Processing order: ${orderId}`);
try {
const order = await orderService.getById(orderId);
if (!order) {
return { status: 404, jsonBody: { error: 'Order not found' } };
}
return { status: 200, jsonBody: order };
} catch (error) {
context.error('Failed to get order', error);
return { status: 500, jsonBody: { error: 'Internal server error' } };
}
},
});
app.serviceBusTopic('processOrderEvent', {
topicName: 'order-events',
subscriptionName: 'order-processor',
connection: 'ServiceBusConnection',
handler: async (message: unknown, context: InvocationContext) => {
const event = message as OrderEvent;
context.log(`Processing event: ${event.type} for order ${event.orderId}`);
await processEvent(event);
},
});
Durable Functions (Orchestrator)
import * as df from 'durable-functions';
df.app.orchestration('orderWorkflow', function* (context) {
const orderId = context.df.getInput() as string;
const order = yield context.df.callActivity('validateOrder', orderId);
const retryOptions = new df.RetryOptions(5000, 3);
yield context.df.callActivityWithRetry('reserveInventory', retryOptions, order);
yield context.df.callActivity('chargePayment', order);
const deadline = new Date(context.df.currentUtcDateTime.getTime() + 24 * 60 * 60 * 1000);
const shippingEvent = context.df.waitForExternalEvent();
timeout = context..(deadline);
winner = context...([shippingEvent, timeout]);
(winner === timeout) {
context..(, orderId);
}
{ orderId, : };
});
Cosmos DB Modeling
interface OrderDocument {
id: string;
partitionKey: string;
type: 'order';
customerId: string;
items: OrderItem[];
total: number;
status: string;
createdAt: string;
_etag?: string;
}
async function updateOrder(order: OrderDocument): Promise<void> {
const container = cosmosClient.database('shop').container('orders');
try {
await container.item(order.id, order.partitionKey).replace(order, {
accessCondition: { type: 'IfMatch', : order. },
});
} (error) {
(error. === ) {
();
}
error;
}
}
changeFeedProcessor = cosmosClient
.()
.()
.()
.({ : , : })
.(leaseContainer)
.( (changes, context) => {
( doc changes) {
({ : , : doc });
}
})
.();
Service Bus Patterns
import { ServiceBusClient, ServiceBusMessage } from '@azure/service-bus';
const client = new ServiceBusClient(process.env.SERVICEBUS_CONNECTION!);
async function sendOrderEvent(event: OrderEvent): Promise<void> {
const sender = client.createSender('order-events');
const message: ServiceBusMessage = {
body: event,
messageId: `${event.orderId}-${event.type}-${Date.now()}`,
subject: event.type,
applicationProperties: { priority: event.priority },
timeToLive: 24 * 60 * 60 * 1000,
};
await sender.sendMessages(message);
await sender.close();
}
async (): <> {
receiver = client.(, , );
messages = receiver.(, { : });
( msg messages) {
{
(msg.);
receiver.(msg);
} {
receiver.(msg);
}
}
receiver.();
}
Bicep Templates
@description('Azure Function App with Service Bus and Cosmos DB')
param location string = resourceGroup().location
param appName string
resource cosmosAccount 'Microsoft.DocumentDB/databaseAccounts@2024-05-15' = {
name: '${appName}-cosmos'
location: location
kind: 'GlobalDocumentDB'
properties: {
databaseAccountOfferType: 'Standard'
consistencyPolicy: { defaultConsistencyLevel: 'Session' }
locations: [{ locationName: location, failoverPriority: 0 }]
}
}
resource serviceBus 'Microsoft.ServiceBus/namespaces@2022-10-01-preview' = {
name: '${appName}-bus'
location: location
sku: { name: 'Standard', tier: 'Standard' }
}
resource functionApp 'Microsoft.Web/sites@2023-12-01' = {
name: '${appName}-func'
location: location
kind: 'functionapp,linux'
identity: { type: 'SystemAssigned' }
properties: {
siteConfig: {
appSettings: [
{ name: 'CosmosDBConnection', value: cosmosAccount.listConnectionStrings().connectionStrings[0].connectionString }
{ name: 'ServiceBusConnection', value: listKeys('${serviceBus.id}/AuthorizationRules/RootManageSharedAccessKey', serviceBus.apiVersion).primaryConnectionString }
]
}
}
}
Checklist
Anti-Patterns
- Cross-partition queries in Cosmos DB (expensive, slow)
- Storing large blobs in Cosmos DB (use Blob Storage + reference)
- Not using sessions for ordered message processing
- Shared Service Bus connection strings across services
- Function apps without Application Insights (blind to failures)
- Cosmos DB with fixed RU provisioning for variable workloads
- Not configuring dead-letter queues on Service Bus subscriptions
- Using host keys for Function auth (use managed identity + RBAC)