Netlify Functions

ServerlessNetlifyEdge FunctionsJAMstackDenoNode.js

Platform

Netlify Functions

Overview

Netlify Functions is a serverless function execution environment optimized for JAMstack architecture, enabling end-to-end web application development seamlessly integrated with static site hosting. It provides two execution environments: traditional Node.js Functions and innovative Edge Functions (Deno Runtime), strongly supporting frontend-centric development workflows from static content delivery to API development, authentication, and real-time processing. As of 2025, with edge computing, streaming, TypeScript support, and GitOps workflow integration, it's rapidly growing as the new standard platform for modern web application development.

Details

Netlify Functions 2025 edition provides a serverless computing environment closely integrated with static site hosting as the core of the JAMstack ecosystem. Particularly noteworthy is the introduction of Edge Functions based on Deno Runtime, achieving ultra-high-speed execution of 50-200ms or less at global edge locations, TypeScript native support, Web Standards-compliant APIs, and streaming capabilities. With Git-linked automatic deployment, preview deployments, A/B testing features, long-running processing via Background Functions, and integrated monitoring and logging capabilities, it provides a complete workflow from development to production.

Key Features

  • Edge Functions: Ultra-fast edge execution (under 50ms) via Deno Runtime
  • Node.js Functions: Traditional serverless functions (up to 15 minutes execution)
  • JAMstack Integration: Seamless integration with static sites
  • TypeScript Support: Native TypeScript support
  • Git Integration: Automatic deployment via GitOps workflows
  • Streaming: Real-time response streaming

Latest 2025 Features

  • Edge Functions: High-speed execution under 50ms with streaming support
  • Background Functions: Long-running asynchronous execution up to 15 minutes
  • Enhanced Deploy Previews: Preview environments for each branch
  • Integrated Monitoring: Real-time function monitoring and log analysis
  • Framework Integration: Deep integration with Astro, Next.js, Nuxt, SvelteKit, etc.

Advantages and Disadvantages

Advantages

  • Integrated development experience specialized for JAMstack architecture
  • World-class low-latency execution environment via Edge Functions
  • Complete automation of development workflows through Git integration
  • Enhanced developer experience with TypeScript/JavaScript dual support
  • Unified management of static hosting and API development
  • Safe development process through preview deployments
  • Rich framework integration and templates

Disadvantages

  • Strong dependency on Netlify platform and vendor lock-in
  • Processing constraints due to Edge Functions execution time limit (50ms)
  • Limited backend functionality compared to other cloud providers
  • Unsuitable for complex database operations or heavy processing
  • Lack of advanced operational features at enterprise level
  • Potential unexpected cost increases due to pay-per-use billing

Reference Pages

Code Examples

Setup and Function Creation

# Install Netlify CLI
npm install -g netlify-cli

# Login to Netlify
netlify login

# Initialize new project
netlify init

# Start local development server
netlify dev

# Create function
netlify functions:create
// netlify/functions/hello.js - Basic Node.js function
exports.handler = async (event, context) => {
    console.log('Event:', JSON.stringify(event, null, 2));
    console.log('Context:', JSON.stringify(context, null, 2));
    
    // CORS headers setup
    const headers = {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Headers': 'Content-Type',
        'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
        'Content-Type': 'application/json'
    };
    
    // Handle preflight request
    if (event.httpMethod === 'OPTIONS') {
        return {
            statusCode: 200,
            headers,
            body: ''
        };
    }
    
    try {
        const { httpMethod, queryStringParameters, body, headers: requestHeaders } = event;
        
        const response = {
            message: 'Hello from Netlify Functions!',
            timestamp: new Date().toISOString(),
            method: httpMethod,
            query: queryStringParameters || {},
            userAgent: requestHeaders['user-agent'] || 'Unknown',
            clientIp: event.headers['client-ip'] || 'Unknown'
        };
        
        return {
            statusCode: 200,
            headers,
            body: JSON.stringify(response, null, 2)
        };
        
    } catch (error) {
        console.error('Function error:', error);
        return {
            statusCode: 500,
            headers,
            body: JSON.stringify({
                error: 'Internal server error',
                message: error.message
            })
        };
    }
};
// netlify/edge-functions/hello-edge.ts - Edge Function (TypeScript)
import { Config } from "https://edge.netlify.com";

export default async (request: Request, context: any): Promise<Response> => {
    const url = new URL(request.url);
    const name = url.searchParams.get("name") || "World";
    const userAgent = request.headers.get("user-agent") || "Unknown";
    const country = context.geo?.country?.name || "Unknown";
    
    // Create response data
    const responseData = {
        message: `Hello, ${name}!`,
        timestamp: new Date().toISOString(),
        userAgent,
        country,
        method: request.method,
        path: url.pathname,
        query: Object.fromEntries(url.searchParams.entries())
    };
    
    // Create JSON response
    const response = new Response(JSON.stringify(responseData, null, 2), {
        status: 200,
        headers: {
            "Content-Type": "application/json",
            "Access-Control-Allow-Origin": "*",
            "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
            "Access-Control-Allow-Headers": "Content-Type, Authorization",
            "Cache-Control": "public, max-age=60"
        }
    });
    
    return response;
};

export const config: Config = {
    path: "/api/hello-edge"
};

HTTP APIs and Request Handling

// netlify/functions/users.ts - RESTful API implementation
import { Handler, HandlerEvent, HandlerContext } from '@netlify/functions';

interface User {
    id: string;
    name: string;
    email: string;
    status: 'active' | 'inactive';
    createdAt: string;
    updatedAt: string;
}

// Demo memory store (use database in production)
let users: User[] = [
    {
        id: '1',
        name: 'John Doe',
        email: '[email protected]',
        status: 'active',
        createdAt: new Date().toISOString(),
        updatedAt: new Date().toISOString()
    }
];

const handler: Handler = async (event: HandlerEvent, context: HandlerContext) => {
    const { httpMethod, queryStringParameters, body, path } = event;
    
    const headers = {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Headers': 'Content-Type, Authorization',
        'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
        'Content-Type': 'application/json'
    };
    
    if (httpMethod === 'OPTIONS') {
        return { statusCode: 200, headers, body: '' };
    }
    
    try {
        switch (httpMethod) {
            case 'GET':
                // User list or filtered search
                const status = queryStringParameters?.status;
                const search = queryStringParameters?.search;
                
                let filteredUsers = users;
                
                if (status) {
                    filteredUsers = filteredUsers.filter(user => user.status === status);
                }
                
                if (search) {
                    filteredUsers = filteredUsers.filter(user => 
                        user.name.toLowerCase().includes(search.toLowerCase()) ||
                        user.email.toLowerCase().includes(search.toLowerCase())
                    );
                }
                
                return {
                    statusCode: 200,
                    headers,
                    body: JSON.stringify({
                        users: filteredUsers,
                        count: filteredUsers.length,
                        filters: { status, search }
                    })
                };
                
            case 'POST':
                // Create new user
                if (!body) {
                    return {
                        statusCode: 400,
                        headers,
                        body: JSON.stringify({ error: 'Request body is required' })
                    };
                }
                
                const userData = JSON.parse(body);
                
                if (!userData.name || !userData.email) {
                    return {
                        statusCode: 400,
                        headers,
                        body: JSON.stringify({ error: 'Name and email are required' })
                    };
                }
                
                const newUser: User = {
                    id: Date.now().toString(),
                    name: userData.name,
                    email: userData.email,
                    status: 'active',
                    createdAt: new Date().toISOString(),
                    updatedAt: new Date().toISOString()
                };
                
                users.push(newUser);
                
                return {
                    statusCode: 201,
                    headers,
                    body: JSON.stringify({
                        message: 'User created successfully',
                        user: newUser
                    })
                };
                
            case 'PUT':
                // Update user information
                if (!body) {
                    return {
                        statusCode: 400,
                        headers,
                        body: JSON.stringify({ error: 'Request body is required' })
                    };
                }
                
                const updateData = JSON.parse(body);
                const userId = queryStringParameters?.id;
                
                if (!userId) {
                    return {
                        statusCode: 400,
                        headers,
                        body: JSON.stringify({ error: 'User ID is required' })
                    };
                }
                
                const userIndex = users.findIndex(user => user.id === userId);
                if (userIndex === -1) {
                    return {
                        statusCode: 404,
                        headers,
                        body: JSON.stringify({ error: 'User not found' })
                    };
                }
                
                users[userIndex] = {
                    ...users[userIndex],
                    ...updateData,
                    updatedAt: new Date().toISOString()
                };
                
                return {
                    statusCode: 200,
                    headers,
                    body: JSON.stringify({
                        message: 'User updated successfully',
                        user: users[userIndex]
                    })
                };
                
            case 'DELETE':
                // Delete user
                const deleteUserId = queryStringParameters?.id;
                
                if (!deleteUserId) {
                    return {
                        statusCode: 400,
                        headers,
                        body: JSON.stringify({ error: 'User ID is required' })
                    };
                }
                
                const deleteIndex = users.findIndex(user => user.id === deleteUserId);
                if (deleteIndex === -1) {
                    return {
                        statusCode: 404,
                        headers,
                        body: JSON.stringify({ error: 'User not found' })
                    };
                }
                
                users.splice(deleteIndex, 1);
                
                return {
                    statusCode: 200,
                    headers,
                    body: JSON.stringify({ message: 'User deleted successfully' })
                };
                
            default:
                return {
                    statusCode: 405,
                    headers,
                    body: JSON.stringify({ error: 'Method not allowed' })
                };
        }
    } catch (error) {
        console.error('API Error:', error);
        return {
            statusCode: 500,
            headers,
            body: JSON.stringify({
                error: 'Internal server error',
                message: error instanceof Error ? error.message : 'Unknown error'
            })
        };
    }
};

export { handler };
// netlify/edge-functions/api-proxy.ts - Edge Function API proxy
import { Config } from "https://edge.netlify.com";

export default async (request: Request, context: any): Promise<Response> => {
    const url = new URL(request.url);
    const apiPath = url.pathname.replace('/api/proxy', '');
    
    // Rate limiting implementation
    const clientIp = request.headers.get('CF-Connecting-IP') || 
                    request.headers.get('X-Forwarded-For') || 
                    'unknown';
    
    const rateLimitKey = `rate_limit_${clientIp}`;
    const requestCount = parseInt(context.cookies.get(rateLimitKey) || '0');
    
    if (requestCount > 100) { // 100 requests per minute limit
        return new Response(JSON.stringify({
            error: 'Rate limit exceeded',
            limit: 100,
            window: '1 minute'
        }), {
            status: 429,
            headers: {
                'Content-Type': 'application/json',
                'Retry-After': '60'
            }
        });
    }
    
    try {
        // Proxy request to external API
        const externalApiUrl = `https://api.external-service.com${apiPath}`;
        
        const proxyRequest = new Request(externalApiUrl, {
            method: request.method,
            headers: {
                'Authorization': `Bearer ${Deno.env.get('EXTERNAL_API_KEY')}`,
                'Content-Type': 'application/json',
                'User-Agent': 'Netlify-Edge-Proxy/1.0'
            },
            body: request.method !== 'GET' ? await request.text() : undefined
        });
        
        const response = await fetch(proxyRequest);
        const data = await response.text();
        
        // Transform/filter response
        let transformedData = data;
        if (response.headers.get('content-type')?.includes('application/json')) {
            const jsonData = JSON.parse(data);
            // Remove sensitive information
            delete jsonData.internal_id;
            delete jsonData.api_key;
            transformedData = JSON.stringify(jsonData);
        }
        
        // Update rate limit counter
        const newCount = requestCount + 1;
        const responseHeaders = new Headers(response.headers);
        responseHeaders.set('Set-Cookie', `${rateLimitKey}=${newCount}; Max-Age=60; HttpOnly`);
        responseHeaders.set('X-Rate-Limit-Remaining', (100 - newCount).toString());
        
        return new Response(transformedData, {
            status: response.status,
            headers: responseHeaders
        });
        
    } catch (error) {
        console.error('Proxy error:', error);
        return new Response(JSON.stringify({
            error: 'Proxy request failed',
            message: error instanceof Error ? error.message : 'Unknown error'
        }), {
            status: 500,
            headers: { 'Content-Type': 'application/json' }
        });
    }
};

export const config: Config = {
    path: "/api/proxy/*"
};

Database Integration and Data Processing

// netlify/functions/database-users.ts - Supabase integration
import { Handler } from '@netlify/functions';
import { createClient } from '@supabase/supabase-js';

const supabaseUrl = process.env.SUPABASE_URL!;
const supabaseServiceKey = process.env.SUPABASE_SERVICE_ROLE_KEY!;

const supabase = createClient(supabaseUrl, supabaseServiceKey);

interface UserRecord {
    id?: string;
    name: string;
    email: string;
    status: 'active' | 'inactive';
    profile?: {
        avatar_url?: string;
        bio?: string;
        website?: string;
    };
    created_at?: string;
    updated_at?: string;
}

const handler: Handler = async (event) => {
    const { httpMethod, queryStringParameters, body } = event;
    
    const headers = {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Headers': 'Content-Type, Authorization',
        'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
        'Content-Type': 'application/json'
    };
    
    if (httpMethod === 'OPTIONS') {
        return { statusCode: 200, headers, body: '' };
    }
    
    try {
        switch (httpMethod) {
            case 'GET':
                // Get user list (with pagination)
                const page = parseInt(queryStringParameters?.page || '1');
                const limit = parseInt(queryStringParameters?.limit || '10');
                const search = queryStringParameters?.search;
                const status = queryStringParameters?.status;
                
                let query = supabase
                    .from('users')
                    .select('*, profiles(*)', { count: 'exact' })
                    .range((page - 1) * limit, page * limit - 1)
                    .order('created_at', { ascending: false });
                
                if (search) {
                    query = query.or(`name.ilike.%${search}%,email.ilike.%${search}%`);
                }
                
                if (status) {
                    query = query.eq('status', status);
                }
                
                const { data: users, error, count } = await query;
                
                if (error) {
                    throw error;
                }
                
                return {
                    statusCode: 200,
                    headers,
                    body: JSON.stringify({
                        users,
                        pagination: {
                            total: count,
                            page,
                            limit,
                            pages: Math.ceil((count || 0) / limit)
                        }
                    })
                };
                
            case 'POST':
                // Create new user
                if (!body) {
                    return {
                        statusCode: 400,
                        headers,
                        body: JSON.stringify({ error: 'Request body is required' })
                    };
                }
                
                const userData: UserRecord = JSON.parse(body);
                
                // Validation
                if (!userData.name || !userData.email) {
                    return {
                        statusCode: 400,
                        headers,
                        body: JSON.stringify({ 
                            error: 'Name and email are required' 
                        })
                    };
                }
                
                // Check email duplicate
                const { data: existingUser } = await supabase
                    .from('users')
                    .select('id')
                    .eq('email', userData.email)
                    .single();
                
                if (existingUser) {
                    return {
                        statusCode: 409,
                        headers,
                        body: JSON.stringify({ 
                            error: 'Email already exists' 
                        })
                    };
                }
                
                // Create user
                const { data: newUser, error: createError } = await supabase
                    .from('users')
                    .insert([{
                        name: userData.name,
                        email: userData.email,
                        status: userData.status || 'active'
                    }])
                    .select()
                    .single();
                
                if (createError) {
                    throw createError;
                }
                
                // Create profile (optional)
                if (userData.profile && newUser) {
                    await supabase
                        .from('profiles')
                        .insert([{
                            user_id: newUser.id,
                            ...userData.profile
                        }]);
                }
                
                return {
                    statusCode: 201,
                    headers,
                    body: JSON.stringify({
                        message: 'User created successfully',
                        user: newUser
                    })
                };
                
            case 'PUT':
                // Update user information
                const userId = queryStringParameters?.id;
                if (!userId) {
                    return {
                        statusCode: 400,
                        headers,
                        body: JSON.stringify({ error: 'User ID is required' })
                    };
                }
                
                if (!body) {
                    return {
                        statusCode: 400,
                        headers,
                        body: JSON.stringify({ error: 'Request body is required' })
                    };
                }
                
                const updateData: Partial<UserRecord> = JSON.parse(body);
                
                const { data: updatedUser, error: updateError } = await supabase
                    .from('users')
                    .update({
                        name: updateData.name,
                        email: updateData.email,
                        status: updateData.status,
                        updated_at: new Date().toISOString()
                    })
                    .eq('id', userId)
                    .select()
                    .single();
                
                if (updateError) {
                    if (updateError.code === 'PGRST116') {
                        return {
                            statusCode: 404,
                            headers,
                            body: JSON.stringify({ error: 'User not found' })
                        };
                    }
                    throw updateError;
                }
                
                return {
                    statusCode: 200,
                    headers,
                    body: JSON.stringify({
                        message: 'User updated successfully',
                        user: updatedUser
                    })
                };
                
            case 'DELETE':
                // Delete user
                const deleteUserId = queryStringParameters?.id;
                if (!deleteUserId) {
                    return {
                        statusCode: 400,
                        headers,
                        body: JSON.stringify({ error: 'User ID is required' })
                    };
                }
                
                const { error: deleteError } = await supabase
                    .from('users')
                    .delete()
                    .eq('id', deleteUserId);
                
                if (deleteError) {
                    throw deleteError;
                }
                
                return {
                    statusCode: 200,
                    headers,
                    body: JSON.stringify({ 
                        message: 'User deleted successfully' 
                    })
                };
                
            default:
                return {
                    statusCode: 405,
                    headers,
                    body: JSON.stringify({ error: 'Method not allowed' })
                };
        }
    } catch (error) {
        console.error('Database error:', error);
        return {
            statusCode: 500,
            headers,
            body: JSON.stringify({
                error: 'Database operation failed',
                message: error instanceof Error ? error.message : 'Unknown error'
            })
        };
    }
};

export { handler };
// netlify/functions/analytics.ts - Analytics data processing
import { Handler } from '@netlify/functions';
import { createClient } from '@supabase/supabase-js';

const supabase = createClient(
    process.env.SUPABASE_URL!,
    process.env.SUPABASE_SERVICE_ROLE_KEY!
);

interface AnalyticsEvent {
    event_type: string;
    user_id?: string;
    session_id: string;
    page_url?: string;
    properties: Record<string, any>;
    timestamp: string;
    user_agent?: string;
    ip_address?: string;
}

const handler: Handler = async (event) => {
    if (event.httpMethod !== 'POST') {
        return {
            statusCode: 405,
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ error: 'Method not allowed' })
        };
    }
    
    try {
        const events: AnalyticsEvent[] = Array.isArray(JSON.parse(event.body || '[]')) 
            ? JSON.parse(event.body || '[]') 
            : [JSON.parse(event.body || '{}')];
        
        // Event validation and normalization
        const validatedEvents = events.map(evt => ({
            ...evt,
            timestamp: evt.timestamp || new Date().toISOString(),
            user_agent: event.headers['user-agent'] || evt.user_agent,
            ip_address: event.headers['client-ip'] || evt.ip_address,
            properties: evt.properties || {}
        }));
        
        // Batch insert to database
        const { error: insertError } = await supabase
            .from('analytics_events')
            .insert(validatedEvents);
        
        if (insertError) {
            throw insertError;
        }
        
        // Update real-time aggregations
        await Promise.all(validatedEvents.map(async (evt) => {
            switch (evt.event_type) {
                case 'page_view':
                    await updatePageViewCounters(evt);
                    break;
                case 'user_interaction':
                    await updateInteractionMetrics(evt);
                    break;
                case 'conversion':
                    await updateConversionFunnels(evt);
                    break;
            }
        }));
        
        return {
            statusCode: 200,
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                message: 'Events processed successfully',
                count: validatedEvents.length
            })
        };
        
    } catch (error) {
        console.error('Analytics error:', error);
        return {
            statusCode: 500,
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                error: 'Failed to process analytics events',
                message: error instanceof Error ? error.message : 'Unknown error'
            })
        };
    }
};

async function updatePageViewCounters(event: AnalyticsEvent) {
    if (!event.page_url) return;
    
    const { error } = await supabase
        .from('page_analytics')
        .upsert({
            page_url: event.page_url,
            view_count: 1,
            last_viewed: event.timestamp
        }, {
            onConflict: 'page_url',
            ignoreDuplicates: false
        });
    
    if (error) {
        console.error('Failed to update page view counters:', error);
    }
}

async function updateInteractionMetrics(event: AnalyticsEvent) {
    if (!event.user_id) return;
    
    const { error } = await supabase
        .from('user_interactions')
        .upsert({
            user_id: event.user_id,
            interaction_type: event.properties.interaction_type,
            interaction_count: 1,
            last_interaction: event.timestamp
        }, {
            onConflict: 'user_id,interaction_type',
            ignoreDuplicates: false
        });
    
    if (error) {
        console.error('Failed to update interaction metrics:', error);
    }
}

async function updateConversionFunnels(event: AnalyticsEvent) {
    const { error } = await supabase
        .from('conversion_events')
        .insert({
            user_id: event.user_id,
            session_id: event.session_id,
            funnel_step: event.properties.step,
            conversion_value: event.properties.value || 0,
            timestamp: event.timestamp
        });
    
    if (error) {
        console.error('Failed to track conversion:', error);
    }
}

export { handler };

Authentication and Security

// netlify/functions/auth-login.ts - JWT authentication
import { Handler } from '@netlify/functions';
import { createClient } from '@supabase/supabase-js';
import * as bcrypt from 'bcryptjs';
import * as jwt from 'jsonwebtoken';

const supabase = createClient(
    process.env.SUPABASE_URL!,
    process.env.SUPABASE_SERVICE_ROLE_KEY!
);

const JWT_SECRET = process.env.JWT_SECRET!;
const JWT_EXPIRES_IN = process.env.JWT_EXPIRES_IN || '7d';

const handler: Handler = async (event) => {
    if (event.httpMethod !== 'POST') {
        return {
            statusCode: 405,
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ error: 'Method not allowed' })
        };
    }
    
    try {
        const { email, password } = JSON.parse(event.body || '{}');
        
        if (!email || !password) {
            return {
                statusCode: 400,
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ 
                    error: 'Email and password are required' 
                })
            };
        }
        
        // Find user
        const { data: user, error } = await supabase
            .from('users')
            .select('id, email, password_hash, name, status, role')
            .eq('email', email)
            .single();
        
        if (error || !user) {
            return {
                statusCode: 401,
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ error: 'Invalid credentials' })
            };
        }
        
        // Verify password
        const isValidPassword = await bcrypt.compare(password, user.password_hash);
        if (!isValidPassword) {
            return {
                statusCode: 401,
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ error: 'Invalid credentials' })
            };
        }
        
        // Check active user
        if (user.status !== 'active') {
            return {
                statusCode: 403,
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ error: 'Account is not active' })
            };
        }
        
        // Generate JWT token
        const token = jwt.sign(
            { 
                userId: user.id, 
                email: user.email,
                role: user.role 
            },
            JWT_SECRET,
            { expiresIn: JWT_EXPIRES_IN }
        );
        
        // Generate refresh token
        const refreshToken = jwt.sign(
            { userId: user.id },
            JWT_SECRET + 'refresh',
            { expiresIn: '30d' }
        );
        
        // Update last login time
        await supabase
            .from('users')
            .update({ last_login_at: new Date().toISOString() })
            .eq('id', user.id);
        
        // Set secure cookies
        const cookieOptions = [
            `token=${token}; HttpOnly; Secure; SameSite=Strict; Max-Age=604800; Path=/`,
            `refreshToken=${refreshToken}; HttpOnly; Secure; SameSite=Strict; Max-Age=2592000; Path=/`
        ];
        
        return {
            statusCode: 200,
            headers: { 
                'Content-Type': 'application/json',
                'Set-Cookie': cookieOptions
            },
            body: JSON.stringify({
                message: 'Login successful',
                user: {
                    id: user.id,
                    name: user.name,
                    email: user.email,
                    role: user.role
                }
            })
        };
        
    } catch (error) {
        console.error('Login error:', error);
        return {
            statusCode: 500,
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                error: 'Authentication failed',
                message: error instanceof Error ? error.message : 'Unknown error'
            })
        };
    }
};

export { handler };
// netlify/edge-functions/auth-middleware.ts - Authentication middleware
import { Config } from "https://edge.netlify.com";
import { verify } from "https://deno.land/x/[email protected]/mod.ts";

interface JWTPayload {
    userId: string;
    email: string;
    role: string;
    iat: number;
    exp: number;
}

export default async (request: Request, context: any): Promise<Response> => {
    const url = new URL(request.url);
    
    // Skip public routes
    const publicPaths = ['/api/auth', '/api/public', '/api/health'];
    if (publicPaths.some(path => url.pathname.startsWith(path))) {
        return context.next();
    }
    
    // Check protected routes
    const protectedPaths = ['/api/admin', '/api/user', '/api/protected'];
    const requiresAuth = protectedPaths.some(path => url.pathname.startsWith(path));
    
    if (!requiresAuth) {
        return context.next();
    }
    
    try {
        // Get token
        const cookies = parseCookies(request.headers.get('cookie') || '');
        const token = cookies.token || request.headers.get('authorization')?.replace('Bearer ', '');
        
        if (!token) {
            return new Response(JSON.stringify({ 
                error: 'Authentication required' 
            }), {
                status: 401,
                headers: { 'Content-Type': 'application/json' }
            });
        }
        
        // Verify token
        const jwtSecret = await crypto.subtle.importKey(
            'raw',
            new TextEncoder().encode(Deno.env.get('JWT_SECRET')),
            { name: 'HMAC', hash: 'SHA-256' },
            false,
            ['verify']
        );
        
        const payload = await verify(token, jwtSecret) as JWTPayload;
        
        // Role-based access control
        if (url.pathname.startsWith('/api/admin') && payload.role !== 'admin') {
            return new Response(JSON.stringify({ 
                error: 'Insufficient permissions' 
            }), {
                status: 403,
                headers: { 'Content-Type': 'application/json' }
            });
        }
        
        // Add user info to headers
        const requestHeaders = new Headers(request.headers);
        requestHeaders.set('x-user-id', payload.userId);
        requestHeaders.set('x-user-email', payload.email);
        requestHeaders.set('x-user-role', payload.role);
        
        const newRequest = new Request(request.url, {
            method: request.method,
            headers: requestHeaders,
            body: request.body
        });
        
        return context.next(newRequest);
        
    } catch (error) {
        console.error('Auth middleware error:', error);
        return new Response(JSON.stringify({ 
            error: 'Invalid token' 
        }), {
            status: 401,
            headers: { 'Content-Type': 'application/json' }
        });
    }
};

function parseCookies(cookieHeader: string): Record<string, string> {
    const cookies: Record<string, string> = {};
    cookieHeader.split(';').forEach(cookie => {
        const [name, value] = cookie.trim().split('=');
        if (name && value) {
            cookies[name] = decodeURIComponent(value);
        }
    });
    return cookies;
}

export const config: Config = {
    path: "/api/*"
};

Event-Driven Architecture

// netlify/functions/webhooks-stripe.ts - Stripe Webhook handling
import { Handler } from '@netlify/functions';
import Stripe from 'stripe';
import { createClient } from '@supabase/supabase-js';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
    apiVersion: '2023-10-16',
});

const supabase = createClient(
    process.env.SUPABASE_URL!,
    process.env.SUPABASE_SERVICE_ROLE_KEY!
);

const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET!;

const handler: Handler = async (event) => {
    if (event.httpMethod !== 'POST') {
        return {
            statusCode: 405,
            body: JSON.stringify({ error: 'Method not allowed' })
        };
    }
    
    const sig = event.headers['stripe-signature'];
    if (!sig) {
        return {
            statusCode: 400,
            body: JSON.stringify({ error: 'Missing stripe signature' })
        };
    }
    
    let stripeEvent: Stripe.Event;
    
    try {
        stripeEvent = stripe.webhooks.constructEvent(
            event.body!, 
            sig, 
            webhookSecret
        );
    } catch (err) {
        console.error('Webhook signature verification failed:', err);
        return {
            statusCode: 400,
            body: JSON.stringify({ error: 'Invalid signature' })
        };
    }
    
    try {
        switch (stripeEvent.type) {
            case 'checkout.session.completed':
                await handleCheckoutCompleted(
                    stripeEvent.data.object as Stripe.Checkout.Session
                );
                break;
                
            case 'invoice.payment_succeeded':
                await handlePaymentSucceeded(
                    stripeEvent.data.object as Stripe.Invoice
                );
                break;
                
            case 'customer.subscription.updated':
                await handleSubscriptionUpdated(
                    stripeEvent.data.object as Stripe.Subscription
                );
                break;
                
            case 'customer.subscription.deleted':
                await handleSubscriptionCanceled(
                    stripeEvent.data.object as Stripe.Subscription
                );
                break;
                
            default:
                console.log(`Unhandled event type: ${stripeEvent.type}`);
        }
        
        return {
            statusCode: 200,
            body: JSON.stringify({ received: true })
        };
        
    } catch (error) {
        console.error('Webhook processing error:', error);
        return {
            statusCode: 500,
            body: JSON.stringify({
                error: 'Webhook processing failed',
                message: error instanceof Error ? error.message : 'Unknown error'
            })
        };
    }
};

async function handleCheckoutCompleted(session: Stripe.Checkout.Session) {
    console.log('Processing checkout completion:', session.id);
    
    // Update subscription information
    if (session.customer && session.subscription) {
        const subscription = await stripe.subscriptions.retrieve(
            session.subscription as string
        );
        
        // Update user subscription status
        await supabase
            .from('user_subscriptions')
            .upsert({
                customer_id: session.customer as string,
                subscription_id: subscription.id,
                status: subscription.status,
                current_period_start: new Date(subscription.current_period_start * 1000),
                current_period_end: new Date(subscription.current_period_end * 1000),
                updated_at: new Date().toISOString()
            });
        
        // Record analytics event
        await fetch(`${process.env.URL}/api/analytics`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                event_type: 'conversion',
                properties: {
                    step: 'subscription_created',
                    value: session.amount_total! / 100,
                    currency: session.currency,
                    subscription_id: session.subscription
                },
                session_id: session.id,
                timestamp: new Date().toISOString()
            })
        });
    }
}

async function handlePaymentSucceeded(invoice: Stripe.Invoice) {
    console.log('Processing successful payment:', invoice.id);
    
    // Save payment record
    await supabase
        .from('payments')
        .insert({
            invoice_id: invoice.id,
            customer_id: invoice.customer as string,
            amount: invoice.amount_paid,
            currency: invoice.currency,
            status: 'succeeded',
            paid_at: new Date(invoice.status_transitions.paid_at! * 1000),
            created_at: new Date().toISOString()
        });
}

async function handleSubscriptionUpdated(subscription: Stripe.Subscription) {
    console.log('Processing subscription update:', subscription.id);
    
    // Update subscription details
    await supabase
        .from('user_subscriptions')
        .update({
            status: subscription.status,
            current_period_start: new Date(subscription.current_period_start * 1000),
            current_period_end: new Date(subscription.current_period_end * 1000),
            cancel_at_period_end: subscription.cancel_at_period_end,
            updated_at: new Date().toISOString()
        })
        .eq('subscription_id', subscription.id);
}

async function handleSubscriptionCanceled(subscription: Stripe.Subscription) {
    console.log('Processing subscription cancellation:', subscription.id);
    
    // Update subscription status
    await supabase
        .from('user_subscriptions')
        .update({
            status: 'canceled',
            canceled_at: new Date().toISOString(),
            updated_at: new Date().toISOString()
        })
        .eq('subscription_id', subscription.id);
}

export { handler };

Monitoring and Performance Optimization

// netlify/functions/health.ts - Health check endpoint
import { Handler } from '@netlify/functions';
import { createClient } from '@supabase/supabase-js';

const supabase = createClient(
    process.env.SUPABASE_URL!,
    process.env.SUPABASE_SERVICE_ROLE_KEY!
);

interface HealthStatus {
    status: 'healthy' | 'unhealthy';
    timestamp: string;
    services: {
        database: 'healthy' | 'unhealthy';
        external_apis: 'healthy' | 'unhealthy';
    };
    metrics: {
        response_time: number;
        memory_usage: number;
        function_region: string;
    };
}

const handler: Handler = async (event, context) => {
    const startTime = Date.now();
    
    try {
        // Check database connectivity
        const dbHealthy = await checkDatabaseHealth();
        
        // Check external APIs
        const externalApisHealthy = await checkExternalApis();
        
        // Calculate metrics
        const responseTime = Date.now() - startTime;
        const memoryUsage = process.memoryUsage().heapUsed / 1024 / 1024; // MB
        
        const allHealthy = dbHealthy && externalApisHealthy;
        
        const healthStatus: HealthStatus = {
            status: allHealthy ? 'healthy' : 'unhealthy',
            timestamp: new Date().toISOString(),
            services: {
                database: dbHealthy ? 'healthy' : 'unhealthy',
                external_apis: externalApisHealthy ? 'healthy' : 'unhealthy'
            },
            metrics: {
                response_time: responseTime,
                memory_usage: Math.round(memoryUsage * 100) / 100,
                function_region: process.env.AWS_REGION || 'unknown'
            }
        };
        
        const statusCode = allHealthy ? 200 : 503;
        return {
            statusCode,
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(healthStatus)
        };
        
    } catch (error) {
        console.error('Health check error:', error);
        
        const errorStatus: HealthStatus = {
            status: 'unhealthy',
            timestamp: new Date().toISOString(),
            services: {
                database: 'unhealthy',
                external_apis: 'unhealthy'
            },
            metrics: {
                response_time: Date.now() - startTime,
                memory_usage: 0,
                function_region: process.env.AWS_REGION || 'unknown'
            }
        };
        
        return {
            statusCode: 503,
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(errorStatus)
        };
    }
};

async function checkDatabaseHealth(): Promise<boolean> {
    try {
        const { data, error } = await supabase
            .from('health_check')
            .select('id')
            .limit(1);
        
        return !error;
    } catch (error) {
        console.error('Database health check failed:', error);
        return false;
    }
}

async function checkExternalApis(): Promise<boolean> {
    try {
        const checks = await Promise.allSettled([
            fetch('https://api.stripe.com/v1', { 
                method: 'HEAD',
                headers: { 'Authorization': `Bearer ${process.env.STRIPE_SECRET_KEY}` }
            }),
            // Add other external API checks as needed
        ]);
        
        return checks.every(result => 
            result.status === 'fulfilled' && 
            result.value.ok
        );
    } catch (error) {
        console.error('External API health check failed:', error);
        return false;
    }
}

export { handler };
# netlify.toml - Project configuration file
[build]
  publish = "dist"
  command = "npm run build"
  functions = "netlify/functions"
  edge_functions = "netlify/edge-functions"

[build.environment]
  NODE_VERSION = "18"

[[redirects]]
  from = "/api/*"
  to = "/.netlify/functions/:splat"
  status = 200

[[edge_functions]]
  function = "auth-middleware"
  path = "/api/*"

[[edge_functions]]
  function = "hello-edge"
  path = "/api/hello-edge"

[[edge_functions]]
  function = "api-proxy"
  path = "/api/proxy/*"

[functions]
  node_bundler = "nft"

[functions."auth-login"]
  external_node_modules = ["bcryptjs", "jsonwebtoken"]

[functions."database-users"]
  external_node_modules = ["@supabase/supabase-js"]

[functions."webhooks-stripe"]
  external_node_modules = ["stripe"]

[dev]
  command = "npm run dev"
  port = 3000
  targetPort = 8888
  framework = "#static"

[context.production.environment]
  NODE_ENV = "production"

[context.deploy-preview.environment]
  NODE_ENV = "staging"

[context.branch-deploy.environment]
  NODE_ENV = "development"

Netlify Functions provides a serverless platform optimized for JAMstack architecture, enabling full-stack development integrated with static site hosting, efficient development workflows through Git integration, and high-speed Edge Functions, establishing a new standard for modern web application development.