API परफ़ॉर्मेंस टेस्टिंग

API performance testing यह मापती है कि किसी API का हर endpoint एक तय load पर कैसे respond करता है: response time के percentiles, throughput, error rate, और वह कितना data भेजता और लेता है। Endpoints को user interface के बिना सीधे एक load generator से call किया जाता है। उदाहरण: एक shop का mobile app peak पर GET /products/{id} को हर second 150 बार call करता है; test जाँचता है कि उस rate पर p95 200 ms या उससे कम रहे और errors 0.1 % से कम हों।

यह इस module की vocabulary (percentiles, workload models, load tests) को एक-एक endpoint पर लागू करती है और तीन सवालों का जवाब देती है: हर endpoint को कौन-सा target पूरा करना है, payload size उस पर कैसे असर डालता है, और एक साथ बहुत-सी requests आने पर endpoint कैसा व्यवहार करता है।

यह क्यों ज़रूरी है

App की हर screen और हर partner integration API calls की एक chain है, इसलिए एक धीमा endpoint उसे call करने वाली हर screen को धीमा कर देता है, और sequential calls में delays जुड़ते जाते हैं। Unbounded list या किसी popular row पर lock जैसी समस्याएँ functional tests में दिखती ही नहीं, क्योंकि वे थोड़े data के साथ एक बार में एक request भेजते हैं।

Tester के लिए endpoint targets "app धीमा लगता है" को एक reportable result में बदल देते हैं: कौन-सा endpoint, कौन-सा percentile, किस load पर, किस target के मुकाबले। API-level tests endpoint बनते ही शुरू हो सकते हैं, पूरे end-to-end load test से बहुत पहले।

पूरे API का नहीं, हर endpoint का अपना target

Endpoints बहुत अलग-अलग काम करते हैं: health check एक constant लौटाता है, lookup एक row पढ़ता है, search हज़ारों records filter करता है, और order बनाना कई tables में लिखता है और शायद payment provider को call करता है। "पूरे API" के लिए एक target, जैसे "सब कुछ 500 ms से कम", हल्के endpoints का regression छिपा देता है और भारी endpoints के लिए असंभव होता है।

Testable target में endpoint और method, percentile (p95, अक्सर p99 भी), threshold, वह load जिस पर target लागू हो, स्वीकार्य error rate और data condition, जैसे page size, सब लिखे होते हैं। Load level के बिना "p95 200 ms से कम" न pass हो सकता है न fail। Targets non-functional requirements या SLOs से, client की ज़रूरत से (जो screen दो endpoints को एक के बाद एक call करती है, उसे अपना time budget बाँटना पड़ता है) और production monitoring से आते हैं। Table एक team का उदाहरण है, कोई standard नहीं।

बड़े export जैसा धीमा काम request को खुला नहीं रखना चाहिए। एक आम design तुरंत 202 Accepted लौटाता है (RFC 9110: processing के लिए स्वीकार, पर पूरी नहीं हुई) और client result बाद में लेता है; तब आप दो targets टेस्ट करते हैं: स्वीकार करने का समय और result तैयार होने तक का समय।

Shop API: targets at the expected peak (an example agreed by one team)

Endpoint                      Load        p95       p99       Errors
GET  /health                  20 req/s    <= 50 ms  <= 100 ms 0 %
GET  /products/{id}           150 req/s   <= 200 ms <= 400 ms < 0.1 %
GET  /products?q=...&limit=20 60 req/s    <= 500 ms <= 1 s    < 0.1 %
POST /orders                  10 req/s    <= 800 ms <= 1.5 s  < 0.1 %
POST /reports/export          1 req/min   202 Accepted <= 300 ms; file ready <= 60 s

आज़माएँ: रिस्पॉन्स टाइम एनालाइज़र आज़माएँ: API परफ़ॉर्मेंस कंपेरेटर

Payload size भी response time का हिस्सा है

Client को दिखने वाले response time में body बनाना, भेजना और parse करना शामिल है। वही endpoint 20 items के साथ तेज़ और 2,000 के साथ धीमा हो सकता है, office network पर तेज़ और mobile connection पर धीमा। हर endpoint को उन sizes पर टेस्ट करें जो वह सच में भेजेगा और लेगा।

  • Body को raw भी मापें और transfer होते समय भी: जब client Accept-Encoding: gzip भेजे, तो क्या response में Content-Encoding है, और उससे कितने bytes बचते हैं?
  • Lists bounded होनी चाहिए: default page size, documented maximum और उससे ऊपर की एक value टेस्ट करें। limit=100000 को cap या reject होना चाहिए, serve नहीं।
  • Data बढ़ाएँ: वही endpoint 5 orders वाले customer और 5,000 orders वाले customer के लिए call करें। Data के साथ बढ़ता समय missing pagination या हर item के लिए एक query की ओर इशारा करता है।
  • Request bodies पर boundary value analysis लगाएँ: batch endpoint का समय 1 item, एक typical संख्या और documented maximum के साथ मापें, फिर maximum से एक item ज़्यादा भेजें और धीमे timeout की जगह एक तेज़, documented 4xx की उम्मीद करें। Server की size limit से बड़ी body के लिए RFC 9110 413 Content Too Large define करता है।

आज़माएँ: रिस्पॉन्स साइज़ एनालाइज़र आज़माएँ: लार्ज JSON डेटासेट जनरेटर

Concurrency: एक तेज़ request बहुत कम साबित करती है

Functional API test एक बार में एक request भेजता है, इसलिए वह best case दिखाता है। Concurrency में requests worker threads, database connections, locks और downstream calls के लिए होड़ करती हैं, और जो endpoint अकेले 80 ms में जवाब देता है वह queue में seconds तक रुक सकता है। पिछले lessons के workload models से load को steps में बढ़ाएँ: single-user baseline, फिर expected peak (analytics या business के forecast के हिसाब से सबसे ज़्यादा अपेक्षित traffic), फिर उससे ऊपर, जो stress testing है। हर step पर p95, p99, throughput और error rate record करें।

Requests कहाँ पहुँचती हैं, यह भी मायने रखता है। कई records पर फैली requests normal path टेस्ट करती हैं; एक ही record पर बहुत-सी requests, जैसे sale में एक discounted product, locking टेस्ट करती हैं। दोनों को जानबूझकर design करें: पहले के लिए अलग-अलग test data, दूसरे के लिए एक "hot" record।

  • सिर्फ़ timing नहीं, correctness भी जाँचें: हर response का status और मुख्य fields assert करें, और run के बाद side effects देखें, जैसे stock oversell न हुआ हो और client के retry करने पर कोई order दो बार न बना हो।
  • Expected refusals को failures से अलग रखें: documented rate limit से ऊपर 429 Too Many Requests (RFC 6585) की उम्मीद करें, और उसे 5xx errors और 504 Gateway Timeout जैसे timeouts से अलग गिनें।

आज़माएँ: Concurrent रिक्वेस्ट टेस्ट जनरेटर

Worked example: sale से पहले एक shop API

एक shop sale वाले weekend की तैयारी कर रहा है। Tester table के product, search और order endpoints को उनके peak rates पर 15 मिनट तक production जैसे size वाले staging environment में चलाता है, 20,000 product ids और 2,000 test customers के साथ, अलग machines पर चल रहे load generators से। Results, जैसे वे report में लिखे जाते हैं:

  • GET /products/{id}: p95 140 ms, p99 260 ms, कोई error नहीं। Target के अंदर।
  • Default limit=20 के साथ GET /products?q=...: p95 430 ms, target के अंदर। Web app का "show all" button limit=200 भेजता है: 1.8 MB uncompressed और p95 1,900 ms। Finding: कोई maximum page size नहीं।
  • कई products पर फैली 10 req/s पर POST /orders: p95 650 ms, target के अंदर। जब 50 virtual users एक साथ एक ही discounted product order करते हैं, तो p95 1,400 ms तक पहुँचता है और 2 % requests 504 Gateway Timeout पर ख़त्म होती हैं। Finding: requests उस product के stock update पर queue में रुकती हैं।
  • Run के बाद stock levels orders से मेल खाते हैं: कुछ oversell नहीं हुआ, कुछ duplicate नहीं बना। यहाँ concurrency की समस्या धीमापन है, data corruption नहीं।
हर endpoint के अपने target के मुकाबले measured p95: lookup 140 ms पर pass, search limit=20 पर pass पर limit=200 पर 1,900 ms, और 50 users के एक ही product खरीदने पर orders 1,400 ms तक।

150 req/s पर GET /products/{id}: p95 target 200 ms

अक्ष 0 ms से 400 ms तक
  • ≤ 200 mstarget के अंदर
  • > 200 mstarget से ऊपर
  1. 1140 ms measured p95, अलग-अलग idsकोई error नहीं; p99 260 ms।पास

60 req/s पर GET /products?q=...: p95 target 500 ms

अक्ष 0 ms से 2000 ms तक
  • ≤ 500 mstarget के अंदर
  • > 500 mstarget से ऊपर
  1. 1430 ms limit=20, default pageपास
  2. 21900 ms limit=200, "show all" button1.8 MB uncompressed: कोई maximum page size नहीं।फ़ेल

10 req/s पर POST /orders: p95 target 800 ms

अक्ष 0 ms से 1600 ms तक
  • ≤ 800 mstarget के अंदर
  • > 800 mstarget से ऊपर
  1. 1650 ms कई products पर फैले ordersपास
  2. 21400 ms 50 users एक साथ एक product order करते हैंएक stock row पर queue; 2 % का अंत 504 पर।फ़ेल

Targets उदाहरण वाली team की सहमति हैं, कोई industry standard नहीं; targets अलग होने के कारण हर axis की अपनी range है।

Tools: एक request से scripted load test तक

Load test के आसपास के steps छोटे tools से हो जाते हैं। Mutqan का Response Time Analyzer ज़्यादा से ज़्यादा 20 sequential requests से एक endpoint की single-user baseline देता है (min, max, average, median और p95); Response Size Analyzer किसी URL या paste की गई body के लिए raw bytes, अनुमानित compressed size और सबसे बड़े fields दिखाता है; API Performance Comparator दो endpoints को साथ-साथ रखता है; HTTP Request Benchmark एक छोटा, bounded benchmark चलाता है। ये tools अपनी requests Mutqan के server से भेजते हैं, इसलिए सिर्फ़ public URLs तक पहुँचते हैं और उनके timings में उस server से network path भी शामिल होता है। इनमें से कोई भी production-scale load नहीं बनाता।

उसके लिए load generator चाहिए। k6 JavaScript scripts चलाता है जिनके thresholds target छूटने पर run को fail कर देते हैं; Apache JMeter GUI में test plans बनाता है, CSV Data Set Config से test data पढ़ता है और असली test के लिए non-GUI mode में चलना चाहिए; Gatling और Locust (Python) दूसरे आम विकल्प हैं। नीचे की k6 script product lookup का target encode करती है। Load test सिर्फ़ उन systems पर करें जो आपके हैं या जिनके लिए लिखित अनुमति है: third-party provider को बिना बताए किया गया load test denial-of-service attack जैसा दिखता है।

// Run: k6 run -e BASE_URL=https://staging.example.com product-lookup.js
import http from 'k6/http';
import { check } from 'k6';
import { SharedArray } from 'k6/data';

// 20,000 product ids: varied data, so requests do not all hit one cached record
const ids = new SharedArray('ids', () =>
  open('./product-ids.txt').split(/\r?\n/).filter(Boolean));

export const options = {
  scenarios: {
    product_lookup: {
      executor: 'constant-arrival-rate', // open model: a fixed rate of new requests
      rate: 150,
      timeUnit: '1s',
      duration: '15m',
      preAllocatedVUs: 50,
      maxVUs: 300,
    },
  },
  thresholds: {
    'http_req_duration{endpoint:product}': ['p(95)<=200', 'p(99)<=400'],
    'http_req_failed{endpoint:product}': ['rate<0.001'],
  },
};

export default function () {
  const id = ids[Math.floor(Math.random() * ids.length)];
  const res = http.get(`${__ENV.BASE_URL}/products/${id}`, {
    tags: { endpoint: 'product' },
  });
  check(res, {
    'status is 200': (r) => r.status === 200,
    'body has a price': (r) => r.status === 200 && r.json('price') !== undefined,
  });
}

आज़माएँ: HTTP रिक्वेस्ट बेंचमार्क आज़माएँ: Concurrent रिक्वेस्ट टेस्ट जनरेटर आज़माएँ: लोड टेस्ट डेटा जनरेटर

आम गलतियाँ

  • पूरे API के लिए एक target: हल्के endpoints के लिए बहुत ढीला, भारी endpoints के लिए असंभव।
  • Load और data condition के बिना target: "p95 200 ms से कम", पर किस request rate और किस page size पर?
  • एक id और छोटे data sets से टेस्ट करना, जिससे हर request को cache से जवाब मिलता है।
  • सिर्फ़ समय मापना: तेज़ 500 या 429 responses latency को अच्छा दिखाते हैं। Status और body assert करें।
  • Payload size को नज़रअंदाज़ करना, क्योंकि test server के बगल से चलता है, जहाँ 2 MB का response भी तेज़ दिखता है।
  • Load generator को API वाली machine पर ही चलाना, या third-party या production API पर बिना अनुमति load test करना।

QA का नज़रिया

Design reviews से शुरू करें। हर नए endpoint के लिए पूछें: उसे कौन और किस क्रम में call करता है, expected peak क्या है, maximum page size क्या है, क्या भारी काम asynchronous है, और rate limit क्या है। Targets पर product owner, developers और operations के साथ सहमति बनाएँ, और उन्हें endpoint के functional acceptance criteria के बगल में लिखें।

हर run के लिए build, environment, dataset, load profile, और हर endpoint के लिए target के मुकाबले p95, p99, throughput, status code के हिसाब से errors और payload size record करें। हर finding ऐसे लिखें कि उस पर काम हो सके: endpoint, load level, target के मुकाबले मापा गया percentile, error का type (जैसे 504 timeouts), saturated resource (यानी वह resource जो सबसे पहले ख़त्म हुआ, जैसे database connections या किसी एक row पर lock) और उसे दिखाने वाले server metrics, और वह re-run जो fix की पुष्टि करे। ज़रूरी endpoints के लिए एक छोटा threshold check pipeline में रखें, ताकि regression उसी commit पर दिखे जिसने उसे पैदा किया।

अभ्यास

Clinic booking API के performance tests plan करें

आपका काम

नीचे के material से clinic booking API के हर endpoint के लिए load और data condition के साथ target लिखें, payload size और concurrency के risks पहचानें, और tests और tools चुनें। आपके targets team की सहमति के लिए एक proposal हैं।

सामग्री
Clinic booking API: expected peak, Sunday 08:00 to 09:00

GET  /clinics/{id}/slots?date=   40 req/s   all slots of one clinic for one day
POST /appointments                5 req/s   books one slot; at 08:00 up to 200
                                            patients try to book the same slot
GET  /appointments?patientId=     8 req/s   visit history; some patients have 300+
GET  /reports/daily               rare      builds a PDF of all bookings of a clinic

Mobile "Book" screen: calls slots, then appointments, in sequence; budget 1.5 s
चरण
  1. हर endpoint के लिए load level और data condition के साथ एक target row लिखें।
  2. Screen के 1.5 s budget को उसकी दो sequential calls में बाँटें।
  3. Payload size और concurrency tests की list बनाएँ, popular slot समेत।
  4. Timing के अलावा checks, और baseline व load run के tools लिखें।
मॉडल उत्तर दिखाएँ
मॉडल उत्तर

उदाहरण targets (proposal, कोई standard नहीं)। Slots: 40 req/s पर p95 300 ms और p99 600 ms, सबसे busy दिन पर। Appointments: 5 req/s पर p95 600 ms और p99 1 s, errors 0.1 % से कम, लिए जा चुके slot के expected conflict response को छोड़कर। History: paginated, 300+ visits वाले patient के लिए 8 req/s पर 20 की page पर p95 400 ms। Report: 300 ms के अंदर 202 Accepted और 60 s के अंदर PDF तैयार; अगर PDF request के अंदर ही बनता है, तो design question उठाएँ।

Budget: 300 ms और 600 ms के बाद 1.5 s में से लगभग 600 ms mobile network और rendering के लिए बचते हैं। दो p95 targets जोड़ना planning का अनुमान है, screen का exact p95 नहीं, इसलिए screen को end to end भी मापें।

Payload और concurrency: सबसे busy दिन का slots response raw और compressed मापें, और history के page sizes maximum तक और उससे ऊपर टेस्ट करें। एक slot के लिए 200 bookings एक साथ भेजें: ठीक एक success (जैसे 201 Created), बाकी के लिए documented conflict (जैसे 409 Conflict), बाद में कोई double booking नहीं, और p99 target के अंदर; फिर कई slots पर फैली bookings के साथ दोहराएँ।

Tools: baselines के लिए Response Time Analyzer और Response Size Analyzer, अगर test environment का public URL हो (वरना saved response को Response Size Analyzer में paste करें), patient ids और dates के लिए Load Test Data Generator, और हर endpoint की शुरुआती k6 script के लिए Concurrent Request Test Generator, जिसके p95 और error-rate thresholds आप अपने targets पर set करें। Load सिर्फ़ test environment में चलाएँ, team की सहमति से।

अक्सर पूछे जाने वाले सवाल

क्या API performance testing और load testing एक ही हैं?

नहीं। Load testing एक test type है: expected load पर system। API performance testing बताती है कि आप कहाँ मापते हैं: API पर, यानी आप endpoints को user interface के बिना सीधे call करते हैं, और उन पर load, stress, spike या soak tests चला सकते हैं। इससे server browser rendering से अलग हो जाता है और हर endpoint को अपना target मिलता है।

अगर कोई targets न दे, तो मैं उन्हें कहाँ से लाऊँ?

Evidence से: production monitoring से हर endpoint का आज का p95 और p99, उसे call करने वाली screens या integrations का time budget, और expected peak। Numbers propose करें, product owner और developers के साथ सहमति बनाएँ, और उन्हें non-functional requirements के रूप में record करें। दूसरे systems के articles से numbers copy न करें।

क्या मैं किसी online tool से API का load test कर सकता हूँ?

Realistic scale पर नहीं। Online tools, Mutqan के performance tools समेत, baselines, comparisons, payload checks और छोटे bounded benchmarks के लिए सही हैं। Realistic concurrency के लिए k6, JMeter, Gatling या Locust जैसा load generator चाहिए, system under test से अलग machines पर, और ऐसे environment पर जिसे load करने की आपको अनुमति हो।

संदर्भ

  • Certified Tester Performance Testing (CT-PT)ISTQB · 2018performance testing पर ISTQB का specialist पाठ्यक्रम: बुनियादी अवधारणाएँ, performance measurements, टेस्ट गतिविधियाँ व कार्य, और टूल।
  • RFC 9110: HTTP SemanticsIETF · 2022HTTP मेथड, हेडर फ़ील्ड, स्टेटस कोड और कंटेंट निगोशिएशन के अर्थ, वायर वर्ज़न से स्वतंत्र।
  • RFC 6585: Additional HTTP Status CodesIETF · 2012428, 429 Too Many Requests, 431 और 511 को परिभाषित करता है, रेट लिमिटिंग के लिए Retry-After हेडर सहित।
  • Grafana k6 documentationGrafana LabsGrafana k6 का आधिकारिक दस्तावेज़ — एक open-source और extensible load व performance testing टूल।

Mutqan tools से अभ्यास करें

रिस्पॉन्स साइज़ का विश्लेषण: कच्चे बनाम compressed बाइट, हेडर का साइज़, JSON ढाँचे का भार और सबसे बड़े फ़ील्ड।

परफ़ॉर्मेंस

किसी सार्वजनिक endpoint पर छोटा, सुरक्षित बेंचमार्क चलाएँ (सीमित रिक्वेस्ट व concurrency) और throughput तथा latency percentile पाएँ।

परफ़ॉर्मेंस

दो endpoint के रिस्पॉन्स टाइम और साइज़ की आमने-सामने तुलना करें (जैसे v1 बनाम v2, staging बनाम production)।

परफ़ॉर्मेंस

और गहराई से

इस topic में आपकी प्रगति

QA रोडमैप का हिस्सा