{"status":"measured","measured_at":"2026-08-05T11:01:02.113637+00:00","feature_count":3,"page":"/app/projects/manufacturing-demo-project","comparison_scope":"Three symmetric product features using the same GS fixtures, risk snapshot and shared business functions; only HTTP adapters differ","environment":{"platform":"macOS-27.0-arm64-arm-64bit-Mach-O","python":"3.14.6","measurement":"local loopback HTTP, separate server processes","rounds":3,"round_order":"alternating framework-first order across rounds and features","connection_mode":"new HTTP connection per request for both servers","fastapi_server":"Uvicorn single worker","flask_server":"Werkzeug development server, threaded","production_benchmark":false},"parity":{"all_feature_responses_equal":true,"feature_count":3,"validation_statuses_match":true,"validation_expected_statuses":true},"validation":{"case_count":5,"all_statuses_match":true,"all_expected_statuses":true,"successful_payloads_equal":true,"cases":[{"feature":"manufacturing_dashboard","name":"limit below minimum","method":"GET","endpoint":"/benchmark/manufacturing-dashboard?limit=0","json_body":null,"expected_status":422,"statuses":{"FastAPI":422,"Flask":422},"status_match":true,"expected_status_match":true,"payload_equal_when_successful":null},{"feature":"risk_event_search","name":"unsupported sort value","method":"GET","endpoint":"/benchmark/risk-events?sort=unsupported","json_body":null,"expected_status":422,"statuses":{"FastAPI":422,"Flask":422},"status_match":true,"expected_status_match":true,"payload_equal_when_successful":null},{"feature":"risk_event_search","name":"valid empty result","method":"GET","endpoint":"/benchmark/risk-events?risk_threshold=1&status=normal","json_body":null,"expected_status":200,"statuses":{"FastAPI":200,"Flask":200},"status_match":true,"expected_status_match":true,"payload_equal_when_successful":true},{"feature":"maintenance_recommendation","name":"invalid operator role","method":"POST","endpoint":"/benchmark/maintenance-recommendation","json_body":{"event_id":"EVT-GS-004","operator_role":"unknown"},"expected_status":422,"statuses":{"FastAPI":422,"Flask":422},"status_match":true,"expected_status_match":true,"payload_equal_when_successful":null},{"feature":"maintenance_recommendation","name":"unknown event","method":"POST","endpoint":"/benchmark/maintenance-recommendation","json_body":{"event_id":"EVT-NOT-FOUND","operator_role":"process_manager"},"expected_status":404,"statuses":{"FastAPI":404,"Flask":404},"status_match":true,"expected_status_match":true,"payload_equal_when_successful":null}]},"implementation":{"shared_service":"framework_comparison.representative_dashboard","fastapi_adapter_loc":50,"flask_adapter_loc":80,"fastapi_validation":"Declarative query/body constraints + response_model","flask_validation":"Manual query parsing + Pydantic body/shared payload"},"features":{"manufacturing_dashboard":{"title":"제조 Dashboard 집계","method":"GET","endpoint":"/benchmark/manufacturing-dashboard?risk_threshold=0.0&limit=8","request_body":null,"comparison_scope":"Aggregate eight risk events, line summaries and sensor series","parity":{"responses_equal":true,"fastapi_payload_sha256":"d073b7fcc1799a947a61a29b70c53777c97b912d8ac17f4ac638678ae8974870","flask_payload_sha256":"d073b7fcc1799a947a61a29b70c53777c97b912d8ac17f4ac638678ae8974870","payload_bytes":{"FastAPI":12428,"Flask":12428}},"implementation":{"fastapi_adapter_loc":15,"flask_adapter_loc":33},"results":{"FastAPI":{"sequential":{"round_count":3,"requests_per_round":300,"request_count":900,"concurrency":1,"connection_mode":"new HTTP connection per request","success_count":900,"error_count":0,"error_rate_percent":0.0,"mean_ms":3.636,"p50_ms":3.4082,"p95_ms":3.823,"p99_ms":11.5824,"throughput_rps":274.56,"wall_seconds":1.0927,"stable_payload":true,"payload_sha256":"0114fac75ba2ad8a4846a8f648c874a1597cf83f0f148e4b4e706f42bbc52248","payload_bytes":11601,"round_metrics":[{"p50_ms":3.3991,"p95_ms":3.823,"p99_ms":11.3168,"throughput_rps":275.5,"error_rate_percent":0.0},{"p50_ms":3.4082,"p95_ms":3.5257,"p99_ms":11.5824,"throughput_rps":274.56,"error_rate_percent":0.0},{"p50_ms":3.4237,"p95_ms":3.8631,"p99_ms":11.6567,"throughput_rps":271.17,"error_rate_percent":0.0}]},"concurrent":{"round_count":3,"requests_per_round":300,"request_count":900,"concurrency":10,"connection_mode":"new HTTP connection per request","success_count":900,"error_count":0,"error_rate_percent":0.0,"mean_ms":9.8971,"p50_ms":7.8964,"p95_ms":17.8237,"p99_ms":20.7399,"throughput_rps":1001.27,"wall_seconds":0.2996,"stable_payload":true,"payload_sha256":"0114fac75ba2ad8a4846a8f648c874a1597cf83f0f148e4b4e706f42bbc52248","payload_bytes":11601,"round_metrics":[{"p50_ms":8.1214,"p95_ms":18.0313,"p99_ms":20.7399,"throughput_rps":980.3,"error_rate_percent":0.0},{"p50_ms":7.8964,"p95_ms":17.8237,"p99_ms":20.939,"throughput_rps":1001.27,"error_rate_percent":0.0},{"p50_ms":7.8874,"p95_ms":17.3425,"p99_ms":19.4562,"throughput_rps":1012.59,"error_rate_percent":0.0}]}},"Flask":{"sequential":{"round_count":3,"requests_per_round":300,"request_count":900,"concurrency":1,"connection_mode":"new HTTP connection per request","success_count":900,"error_count":0,"error_rate_percent":0.0,"mean_ms":3.6159,"p50_ms":3.3705,"p95_ms":3.6115,"p99_ms":11.7216,"throughput_rps":276.05,"wall_seconds":1.0868,"stable_payload":true,"payload_sha256":"362fa207051c66909079646e21b32703dc1c51a9fabc911ed4fe6752c6d257d0","payload_bytes":11965,"round_metrics":[{"p50_ms":3.2636,"p95_ms":3.4707,"p99_ms":11.3342,"throughput_rps":287.4,"error_rate_percent":0.0},{"p50_ms":3.3803,"p95_ms":3.9732,"p99_ms":11.7483,"throughput_rps":272.83,"error_rate_percent":0.0},{"p50_ms":3.3705,"p95_ms":3.6115,"p99_ms":11.7216,"throughput_rps":276.05,"error_rate_percent":0.0}]},"concurrent":{"round_count":3,"requests_per_round":300,"request_count":900,"concurrency":10,"connection_mode":"new HTTP connection per request","success_count":900,"error_count":0,"error_rate_percent":0.0,"mean_ms":10.1011,"p50_ms":8.0787,"p95_ms":18.2752,"p99_ms":23.4696,"throughput_rps":979.18,"wall_seconds":0.3064,"stable_payload":true,"payload_sha256":"362fa207051c66909079646e21b32703dc1c51a9fabc911ed4fe6752c6d257d0","payload_bytes":11965,"round_metrics":[{"p50_ms":8.0787,"p95_ms":18.6735,"p99_ms":22.6569,"throughput_rps":988.18,"error_rate_percent":0.0},{"p50_ms":7.9835,"p95_ms":18.0648,"p99_ms":26.5634,"throughput_rps":979.18,"error_rate_percent":0.0},{"p50_ms":8.4041,"p95_ms":18.2752,"p99_ms":23.4696,"throughput_rps":975.98,"error_rate_percent":0.0}]}}},"performance_scores":{"FastAPI":4.92,"Flask":4.94}},"risk_event_search":{"title":"위험 이벤트 검색·필터","method":"GET","endpoint":"/benchmark/risk-events?risk_threshold=0.6&status=warning&sort=probability_desc&limit=5&offset=0","request_body":null,"comparison_scope":"Filter, sort and paginate product risk events","parity":{"responses_equal":true,"fastapi_payload_sha256":"87d6788ce00a2ec53c5cf19fa9e6611d7efe7d4e2989a14e07dadaa88f625ba4","flask_payload_sha256":"87d6788ce00a2ec53c5cf19fa9e6611d7efe7d4e2989a14e07dadaa88f625ba4","payload_bytes":{"FastAPI":2193,"Flask":2193}},"implementation":{"fastapi_adapter_loc":23,"flask_adapter_loc":56},"results":{"FastAPI":{"sequential":{"round_count":3,"requests_per_round":300,"request_count":900,"concurrency":1,"connection_mode":"new HTTP connection per request","success_count":900,"error_count":0,"error_rate_percent":0.0,"mean_ms":3.5782,"p50_ms":3.3308,"p95_ms":3.6527,"p99_ms":11.6175,"throughput_rps":278.96,"wall_seconds":1.0754,"stable_payload":true,"payload_sha256":"ed70b172533da4eeb45761cfb3d978d039b10bc7ca18a0da3571c75c46b67e1e","payload_bytes":2058,"round_metrics":[{"p50_ms":3.3308,"p95_ms":3.5398,"p99_ms":11.6175,"throughput_rps":279.52,"error_rate_percent":0.0},{"p50_ms":3.3402,"p95_ms":3.6527,"p99_ms":11.6304,"throughput_rps":278.96,"error_rate_percent":0.0},{"p50_ms":3.3265,"p95_ms":3.659,"p99_ms":11.4756,"throughput_rps":274.9,"error_rate_percent":0.0}]},"concurrent":{"round_count":3,"requests_per_round":300,"request_count":900,"concurrency":10,"connection_mode":"new HTTP connection per request","success_count":900,"error_count":0,"error_rate_percent":0.0,"mean_ms":9.9298,"p50_ms":7.9047,"p95_ms":17.3627,"p99_ms":18.7136,"throughput_rps":999.0,"wall_seconds":0.3003,"stable_payload":true,"payload_sha256":"ed70b172533da4eeb45761cfb3d978d039b10bc7ca18a0da3571c75c46b67e1e","payload_bytes":2058,"round_metrics":[{"p50_ms":7.9047,"p95_ms":18.1582,"p99_ms":20.284,"throughput_rps":999.0,"error_rate_percent":0.0},{"p50_ms":7.8543,"p95_ms":17.3627,"p99_ms":18.3612,"throughput_rps":1017.72,"error_rate_percent":0.0},{"p50_ms":8.3232,"p95_ms":17.1769,"p99_ms":18.7136,"throughput_rps":992.47,"error_rate_percent":0.0}]}},"Flask":{"sequential":{"round_count":3,"requests_per_round":300,"request_count":900,"concurrency":1,"connection_mode":"new HTTP connection per request","success_count":900,"error_count":0,"error_rate_percent":0.0,"mean_ms":3.4718,"p50_ms":3.2242,"p95_ms":3.5578,"p99_ms":11.6445,"throughput_rps":287.49,"wall_seconds":1.0435,"stable_payload":true,"payload_sha256":"620d7dcd6be72be2d5b045d30ff8c2a36ea9e45f137d7635ad7dd7bd08f4f359","payload_bytes":2197,"round_metrics":[{"p50_ms":3.2242,"p95_ms":3.586,"p99_ms":11.5878,"throughput_rps":287.0,"error_rate_percent":0.0},{"p50_ms":3.232,"p95_ms":3.499,"p99_ms":11.6445,"throughput_rps":287.49,"error_rate_percent":0.0},{"p50_ms":3.2222,"p95_ms":3.5578,"p99_ms":11.6888,"throughput_rps":289.38,"error_rate_percent":0.0}]},"concurrent":{"round_count":3,"requests_per_round":300,"request_count":900,"concurrency":10,"connection_mode":"new HTTP connection per request","success_count":900,"error_count":0,"error_rate_percent":0.0,"mean_ms":9.4685,"p50_ms":7.4828,"p95_ms":17.9439,"p99_ms":20.3548,"throughput_rps":1026.44,"wall_seconds":0.2923,"stable_payload":true,"payload_sha256":"620d7dcd6be72be2d5b045d30ff8c2a36ea9e45f137d7635ad7dd7bd08f4f359","payload_bytes":2197,"round_metrics":[{"p50_ms":7.478,"p95_ms":17.5931,"p99_ms":18.7509,"throughput_rps":1026.44,"error_rate_percent":0.0},{"p50_ms":7.4828,"p95_ms":19.0312,"p99_ms":22.9193,"throughput_rps":1020.68,"error_rate_percent":0.0},{"p50_ms":7.5583,"p95_ms":17.9439,"p99_ms":20.3548,"throughput_rps":1041.17,"error_rate_percent":0.0}]}}},"performance_scores":{"FastAPI":4.9,"Flask":4.96}},"maintenance_recommendation":{"title":"정비 조치 추천","method":"POST","endpoint":"/benchmark/maintenance-recommendation","request_body":{"event_id":"EVT-GS-004","operator_role":"process_manager","include_evidence":true},"comparison_scope":"Validate a POST body and apply a deterministic maintenance rule","parity":{"responses_equal":true,"fastapi_payload_sha256":"3a13a15f7db52dd4c3edd828c874494819ac66c100f2fae311a7af5cfb1a673a","flask_payload_sha256":"3a13a15f7db52dd4c3edd828c874494819ac66c100f2fae311a7af5cfb1a673a","payload_bytes":{"FastAPI":1290,"Flask":1290}},"implementation":{"fastapi_adapter_loc":12,"flask_adapter_loc":13},"results":{"FastAPI":{"sequential":{"round_count":3,"requests_per_round":300,"request_count":900,"concurrency":1,"connection_mode":"new HTTP connection per request","success_count":900,"error_count":0,"error_rate_percent":0.0,"mean_ms":3.5751,"p50_ms":3.3172,"p95_ms":3.6473,"p99_ms":11.6836,"throughput_rps":279.21,"wall_seconds":1.0745,"stable_payload":true,"payload_sha256":"8ca55514f40329d318cd7cb24b48c3aed03c68123cc0e81c00d2f0a532a5ca50","payload_bytes":1222,"round_metrics":[{"p50_ms":3.3172,"p95_ms":3.6473,"p99_ms":11.6597,"throughput_rps":277.62,"error_rate_percent":0.0},{"p50_ms":3.2961,"p95_ms":3.5204,"p99_ms":11.6836,"throughput_rps":282.63,"error_rate_percent":0.0},{"p50_ms":3.3229,"p95_ms":3.6624,"p99_ms":12.057,"throughput_rps":279.21,"error_rate_percent":0.0}]},"concurrent":{"round_count":3,"requests_per_round":300,"request_count":900,"concurrency":10,"connection_mode":"new HTTP connection per request","success_count":900,"error_count":0,"error_rate_percent":0.0,"mean_ms":9.6755,"p50_ms":7.8068,"p95_ms":17.616,"p99_ms":20.3067,"throughput_rps":1010.78,"wall_seconds":0.2968,"stable_payload":true,"payload_sha256":"8ca55514f40329d318cd7cb24b48c3aed03c68123cc0e81c00d2f0a532a5ca50","payload_bytes":1222,"round_metrics":[{"p50_ms":7.5726,"p95_ms":17.5696,"p99_ms":18.484,"throughput_rps":1057.07,"error_rate_percent":0.0},{"p50_ms":7.8068,"p95_ms":17.616,"p99_ms":20.3067,"throughput_rps":1010.78,"error_rate_percent":0.0},{"p50_ms":9.3273,"p95_ms":21.1105,"p99_ms":27.8067,"throughput_rps":886.66,"error_rate_percent":0.0}]}},"Flask":{"sequential":{"round_count":3,"requests_per_round":300,"request_count":900,"concurrency":1,"connection_mode":"new HTTP connection per request","success_count":900,"error_count":0,"error_rate_percent":0.0,"mean_ms":3.4789,"p50_ms":3.2191,"p95_ms":3.4648,"p99_ms":11.774,"throughput_rps":286.91,"wall_seconds":1.0456,"stable_payload":true,"payload_sha256":"d195d7d883eebadf413db041b8e6b15cf0bb6b905bea6d9926b5ca9aa1c67022","payload_bytes":1556,"round_metrics":[{"p50_ms":3.2171,"p95_ms":3.4648,"p99_ms":11.4978,"throughput_rps":290.19,"error_rate_percent":0.0},{"p50_ms":3.2191,"p95_ms":3.4774,"p99_ms":11.774,"throughput_rps":286.91,"error_rate_percent":0.0},{"p50_ms":3.2447,"p95_ms":3.398,"p99_ms":11.9313,"throughput_rps":286.41,"error_rate_percent":0.0}]},"concurrent":{"round_count":3,"requests_per_round":300,"request_count":900,"concurrency":10,"connection_mode":"new HTTP connection per request","success_count":900,"error_count":0,"error_rate_percent":0.0,"mean_ms":10.1051,"p50_ms":8.2141,"p95_ms":19.0106,"p99_ms":21.69,"throughput_rps":973.31,"wall_seconds":0.3082,"stable_payload":true,"payload_sha256":"d195d7d883eebadf413db041b8e6b15cf0bb6b905bea6d9926b5ca9aa1c67022","payload_bytes":1556,"round_metrics":[{"p50_ms":7.8616,"p95_ms":18.7966,"p99_ms":21.69,"throughput_rps":993.75,"error_rate_percent":0.0},{"p50_ms":8.2141,"p95_ms":19.0106,"p99_ms":20.7807,"throughput_rps":973.31,"error_rate_percent":0.0},{"p50_ms":8.2563,"p95_ms":20.6689,"p99_ms":26.3381,"throughput_rps":921.41,"error_rate_percent":0.0}]}}},"performance_scores":{"FastAPI":4.9,"Flask":4.86}}},"performance_score_formula":"Per feature: equal average of normalized sequential p95, sequential throughput, concurrent p95 and concurrent throughput. Overall: arithmetic mean of three feature scores.","performance_scores":{"FastAPI":4.91,"Flask":4.92},"limitations":["Local Mac loopback measurement; not a cloud production benchmark.","FastAPI and Flask use their normal local servers, so the result includes server-stack overhead.","The shared functions use eight product GS fixtures and do not include a remote database or external model call."]}