Optimizing API Performance with Response Payload Compression

Introduction

In modern web applications, API response sizes can significantly impact performance, especially when dealing with large datasets, nested objects, or extensive user listings. Response payload compression is a critical optimization technique that can reduce bandwidth usage by up to 70-90% and improve application responsiveness.

This tutorial demonstrates how to implement response compression using Node.js built in package for compression with Brotli compression.

require('zlib')

Why Response Compression Matters

When APIs return large datasets containing:

  • Extensive user listings with nested properties
  • Complex object hierarchies
  • Large JSON responses with repetitive data structures
  • File content or base64-encoded data

Uncompressed responses can lead to:

  • Increased bandwidth costs
  • Slower page load times
  • Poor user experience on mobile networks
  • Higher server resource utilization

Implementation Overview

Core Implementation with Brotli Compression

Here’s a practical implementation using Node.js and the zlib package:
This is a handler which returns the list of users lets consider we have to return a complex nested object which will increase the payload size.

const { ResponseHelper } = require('./ResponseClass')

async function handler() {
    let options = {}
    options.compress = true
    
    const response = new ResponseHelper(options)
    
    const res = await response.ok({
        message: "Success",
        data: {  
            users: [
                {
                    id: 1,
                    name: "Jack Thompson",
                    email: "jack.thompson@company.com",
                    profile: {
                        avatar: "https://cdn.company.com/avatars/jack_1024x1024.jpg",
                        bio: "Senior Software Engineer with 8+ years of experience in full-stack development",
                        skills: ["JavaScript", "Python", "React", "Node.js", "AWS", "Docker"],
                        certifications: [
                            { name: "AWS Solutions Architect", issuer: "Amazon", year: 2023 },
                            { name: "Kubernetes Administrator", issuer: "CNCF", year: 2022 }
                        ]
                    },
                    employment: {
                        department: "Engineering",
                        position: "Senior Software Engineer",
                        level: "L5",
                        salary: 95000,
                        startDate: "2019-03-15",
                        manager: { id: 15, name: "Sarah Wilson" },
                        team: {
                            name: "Platform Engineering",
                            members: 12,
                            projects: ["API Gateway", "Microservices Migration", "DevOps Pipeline"]
                        }
                    },
                    permissions: {
                        roles: ["developer", "code_reviewer", "mentor"],
                        accessLevels: ["production_read", "staging_write", "development_admin"],
                        repositories: ["frontend-app", "backend-api", "shared-components"]
                    },
                    activity: {
                        lastLogin: "2024-06-25T14:30:00Z",
                        projectsCount: 23,
                        commitsThisMonth: 47,
                        reviewsCompleted: 15,
                        mentoringSessions: 8
                    }
                },
                {
                    id: 2,
                    name: "Olivia Rodriguez",
                    email: "olivia.rodriguez@company.com",
                    profile: {
                        avatar: "https://cdn.company.com/avatars/olivia_1024x1024.jpg",
                        bio: "Product Marketing Manager driving user acquisition and retention strategies",
                        skills: ["Product Marketing", "Analytics", "A/B Testing", "SQL", "Figma", "Salesforce"],
                        certifications: [
                            { name: "Google Analytics Certified", issuer: "Google", year: 2023 },
                            { name: "Product Marketing Core", issuer: "Product Marketing Alliance", year: 2022 }
                        ]
                    },
                    employment: {
                        department: "Marketing",
                        position: "Product Marketing Manager",
                        level: "M3",
                        salary: 78000,
                        startDate: "2021-08-20",
                        manager: { id: 8, name: "Michael Chen" },
                        team: {
                            name: "Growth Marketing",
                            members: 8,
                            projects: ["Q3 Campaign Launch", "User Onboarding Optimization", "Competitive Analysis"]
                        }
                    },
                    permissions: {
                        roles: ["marketer", "analyst", "campaign_manager"],
                        accessLevels: ["analytics_full", "crm_write", "social_media_admin"],
                        tools: ["Google Analytics", "Salesforce", "HubSpot", "Figma", "Looker"]
                    },
                    activity: {
                        lastLogin: "2024-06-26T09:15:00Z",
                        campaignsLaunched: 12,
                        reportsGenerated: 28,
                        meetingsAttended: 35,
                        presentationsGiven: 6
                    }
                },
    })
    
    return res;
}

handler()

So let’s try to implement this using the HTTPS Response Helper class where we can control the compression of data if its required.

ResponseHelper Implementation

The ResponseHelper class handles compression internally:

//ResponseClass
const zlib = require('zlib')

class ResponseHelper {
    constructor(options = {}) {
        this.compress = options.compress || false
    }
    
    async ok(data) {
        const jsonResponse = JSON.stringify(data)
        
        if (this.compress) {
            const compressed = await this.compressResponse(jsonResponse)
            return {
                statusCode: 200,
                headers: {
                    'Content-Type': 'application/json',
                    'Content-Encoding': 'br'
                },
                body: compressed.toString('base64'),
                isBase64Encoded: true
            }
        }
        
        return {
            statusCode: 200,
            headers: {
                'Content-Type': 'application/json'
            },
            body: jsonResponse
        }
    }
    
    compressResponse(data) {
        return new Promise((resolve, reject) => {
            zlib.brotliCompress(data, (err, compressed) => {
                if (err) reject(err)
                else resolve(compressed)
            })
        })
    }
}

The key’s isBase64Encoded: true helps the browser understand that the content is encoded in base64 and 'Content-Encoding': 'br' helps the browser in understand the Compression used for the content.

Compression Techniques Comparison

Brotli Compression
  • Best compression ratio: Up to 20% better than gzip
  • Optimized for web content: Particularly effective with JSON and HTML
  • Browser support: Modern browsers (Chrome 50+, Firefox 44+)
  • Use case: Production APIs with modern client support
Gzip Compression
  • Universal support: Supported by all browsers
  • Good compression ratio: Standard web compression
  • Fast processing: Lower CPU overhead
  • Good for Dynamic Content: If you need to compress content on the fly, Gzip might be a better choice due to its faster compression speed.
  • Use case: Legacy browser support required
Deflate Compression
  • Basic compression: Older standard
  • Minimal overhead: Fastest processing
  • Limited effectiveness: Lower compression ratios
  • Use case: Resource-constrained environments

Best Practices

When to Enable Compression
  • Large JSON responses (>1KB)
  • Repetitive data structures
  • High-traffic APIs
  • Mobile-first applications
When to Avoid Compression
  • Very small responses (<500 bytes)
  • Already compressed content (images, videos)
  • Real-time applications requiring minimal latency
  • CPU-constrained environments

Conclusion

Response payload compression is a powerful optimization technique that can significantly improve API performance with minimal implementation effort. By leveraging Brotli compression in Node.js applications you can achieve substantial bandwidth savings and improved user experience.

Contributors: @ashwathprabhu

Additional Resources

4 Likes