[{"data":1,"prerenderedAt":2667},["ShallowReactive",2],{"blog-post-\u002Fblog\u002Fkafka-python-clients":3},{"id":4,"title":5,"body":6,"date":2653,"description":2654,"extension":2655,"meta":2656,"navigation":1007,"ogImage":2657,"path":2658,"pinned":2659,"seo":2660,"sitemap":2661,"stem":2662,"tags":2663,"__hash__":2666},"blog\u002Fblog\u002Fkafka-python-clients.md","Kafka Python Clients 2026: Which Should You Choose?",{"type":7,"value":8,"toc":2624},"minimark",[9,13,29,34,146,150,153,156,163,167,174,325,328,331,334,344,351,356,365,374,379,382,384,397,401,404,413,418,424,426,438,442,451,457,471,476,481,485,488,492,546,550,665,668,672,809,816,820,892,895,899,918,922,925,933,948,966,970,980,1704,1713,1722,1730,1734,1744,2413,2425,2441,2447,2450,2458,2462,2465,2468,2488,2491,2494,2498,2502,2505,2552,2556,2562,2566,2577,2581,2587,2591,2594,2598,2610,2617,2620],[10,11,12],"p",{},"Choosing a Kafka Python client is not mainly about producer and consumer syntax. All three clients covered here can send messages to Kafka and consume them. The important differences are whether the API is synchronous or built for asyncio, whether the client depends on native code, how easy it is to install and deploy, how it integrates with Schema Registry, and how actively the project is maintained.",[10,14,15,16,20,21,24,25,28],{},"This guide compares ",[17,18,19],"code",{},"confluent-kafka",", ",[17,22,23],{},"kafka-python",", and ",[17,26,27],{},"aiokafka"," using two independent kinds of evidence: manually verified technical capabilities and GitHub repository metrics captured in a dated snapshot. The capability comparison shows whether a client meets your requirements. The repository metrics show recent maintenance activity, visible interest, and usage in public repositories.",[30,31,33],"h2",{"id":32},"quick-decision","Quick decision",[35,36,37,53],"table",{},[38,39,40],"thead",{},[41,42,43,47,50],"tr",{},[44,45,46],"th",{},"Situation",[44,48,49],{},"Best starting point",[44,51,52],{},"Main caveat",[54,55,56,69,84,96,108,120,131],"tbody",{},[41,57,58,62,66],{},[59,60,61],"td",{},"Synchronous producer or consumer service",[59,63,64],{},[17,65,19],{},[59,67,68],{},"Needs the librdkafka native wheel to fit your deployment target.",[41,70,71,74,78],{},[59,72,73],{},"FastAPI or asyncio application",[59,75,76],{},[17,77,27],{},[59,79,80,81,83],{},"Consider ",[17,82,19],{}," for Schema Registry or mixed sync\u002Fasync use.",[41,85,86,89,93],{},[59,87,88],{},"High-throughput Kafka application",[59,90,91],{},[17,92,19],{},[59,94,95],{},"Benchmark your own workload before deciding.",[41,97,98,101,105],{},[59,99,100],{},"Application using Schema Registry",[59,102,103],{},[17,104,19],{},[59,106,107],{},"Install the Schema Registry extras and verify serializer settings.",[41,109,110,113,117],{},[59,111,112],{},"Project that must install without a native extension",[59,114,115],{},[17,116,23],{},[59,118,119],{},"Optional compression and CRC extras can still add native dependencies.",[41,121,122,125,128],{},[59,123,124],{},"Migrating from kafka-python",[59,126,127],{},"Stay unless a requirement justifies the change",[59,129,130],{},"Switch only for a concrete requirement such as Schema Registry, librdkafka, or commercial backing.",[41,132,133,136,143],{},[59,134,135],{},"Stateful stream processing with windows, joins, or local state",[59,137,138],{},[139,140,142],"a",{"href":141},"\u002Fblog\u002Fkafka-streams-in-python","Compare Faust and Quix Streams",[59,144,145],{},"A stream-processing framework changes the application and deployment model.",[30,147,149],{"id":148},"kafka-clients-vs-stream-processing","Kafka clients vs. stream processing",[10,151,152],{},"\"Kafka Python client\" is often used loosely. It can mean a general-purpose library that an application uses to produce and consume Kafka messages, or a stream-processing framework such as Faust Streaming or Quix Streams. This guide compares the first kind.",[10,154,155],{},"With a general-purpose client, your application decides what to do with each message, where to keep the state needed for processing, and what should happen when processing fails. The client provides Producer, Consumer, and Admin APIs and handles authentication with Kafka. This is usually the right choice for request-driven services, background workers, event publishers, and consumers whose business logic already lives in FastAPI, Django, or another application framework.",[10,157,158,159,162],{},"A stream-processing framework does more than talk to Kafka: it organizes how messages move from input topics through processing steps to output topics, and it manages the state used by those steps. You may need one to count events per user in five-minute windows, join orders with payments by ID, or maintain an aggregate that can recover after a restart. Most services do not need this additional layer. If yours does, see the separate ",[139,160,161],{"href":141},"Faust Streaming vs. Quix Streams comparison",".",[30,164,166],{"id":165},"kafka-python-clients-compared","Kafka Python clients compared",[10,168,169,173],{},[170,171,172],"strong",{},"Capabilities verified against official documentation and package artifacts:"," 12 Aug 2026",[35,175,176,192],{},[38,177,178],{},[41,179,180,183,186,189],{},[44,181,182],{},"Capability",[44,184,185],{},"confluent-kafka 2.15.0",[44,187,188],{},"kafka-python 3.0.10",[44,190,191],{},"aiokafka 0.14.0",[54,193,194,208,230,244,258,279,312],{},[41,195,196,199,202,205],{},[59,197,198],{},"Python support",[59,200,201],{},"Python 3.8+; CPython",[59,203,204],{},"Python 3.8+; CPython and PyPy",[59,206,207],{},"Python 3.10+; CPython",[41,209,210,213,220,225],{},[59,211,212],{},"Type-checker support",[59,214,215,216,219],{},"Official (",[17,217,218],{},"py.typed",")",[59,221,222,223],{},"Partial stubs, but no ",[17,224,218],{},[59,226,227,228],{},"C-extension stubs only; no ",[17,229,218],{},[41,231,232,235,238,241],{},[59,233,234],{},"API model",[59,236,237],{},"Synchronous; AsyncIO also available",[59,239,240],{},"Synchronous",[59,242,243],{},"Asyncio-native",[41,245,246,249,252,255],{},[59,247,248],{},"Installation",[59,250,251],{},"Native librdkafka; platform-specific wheels",[59,253,254],{},"Pure Python; universal wheel",[59,256,257],{},"Native extension; platform-specific wheels",[41,259,260,263,266,268],{},[59,261,262],{},"Admin API",[59,264,265],{},"Yes",[59,267,265],{},[59,269,270,271],{},"Experimental ",[139,272,276],{"href":273,"rel":274},"https:\u002F\u002Fgithub.com\u002Faio-libs\u002Faiokafka\u002Fblob\u002Fv0.14.0\u002Faiokafka\u002Fadmin\u002Fclient.py",[275],"nofollow",[17,277,278],{},"AIOKafkaAdminClient",[41,280,281,284,298,305],{},[59,282,283],{},"Cooperative rebalancing",[59,285,286,291,292,297],{},[139,287,290],{"href":288,"rel":289},"https:\u002F\u002Fgithub.com\u002Fconfluentinc\u002Flibrdkafka\u002Fblob\u002Fv2.15.0\u002FCONFIGURATION.md?plain=1#L130",[275],"Supported (opt-in)","; ",[139,293,296],{"href":294,"rel":295},"https:\u002F\u002Fdocs.confluent.io\u002Fkafka-clients\u002Fpython\u002Fcurrent\u002Fchangelog.html#kip-848-general-availability",[275],"KIP-848"," also available",[59,299,300],{},[139,301,304],{"href":302,"rel":303},"https:\u002F\u002Fkafka-python.readthedocs.io\u002Fen\u002F3.0.10\u002Fupgrade_to_3_0.html#incremental-cooperative-rebalance",[275],"Supported (opt-in via KIP-429)",[59,306,307],{},[139,308,311],{"href":309,"rel":310},"https:\u002F\u002Fgithub.com\u002Faio-libs\u002Faiokafka\u002Fissues\u002F1126",[275],"Not supported; eager only",[41,313,314,317,320,323],{},[59,315,316],{},"Schema Registry",[59,318,319],{},"Built in: Avro, Protobuf, and JSON Schema",[59,321,322],{},"Separate library required",[59,324,322],{},[10,326,327],{},"All three clients support idempotent production, transactions, and PLAIN, GSSAPI, SCRAM-SHA-256\u002F512, and OAUTHBEARER authentication.",[10,329,330],{},"The table shows what each client supports; the sections below explain how each one works and when to choose it.",[332,333,19],"h3",{"id":19},[10,335,336,340,341,343],{},[139,337,19],{"href":338,"rel":339},"https:\u002F\u002Fdocs.confluent.io\u002Fplatform\u002Fcurrent\u002Fclients\u002Fconfluent-kafka-python\u002Fhtml\u002Findex.html",[275]," is a Python binding for librdkafka, a native Kafka client. Librdkafka handles the Kafka protocol, batching, compression, retries, and consumer groups, while Python configures the client and handles records and callbacks. Keeping these hot paths in librdkafka's multithreaded C core reduces Python-level work, which is why ",[17,342,19],{}," is the first client to benchmark for throughput-sensitive workloads.",[10,345,346,347,350],{},"Its established APIs are synchronous. Consumers read messages with ",[17,348,349],{},"poll()",", while producers report delivery results through callbacks.",[10,352,353],{},[170,354,355],{},"Capabilities and limitations",[10,357,358,359,364],{},"It provides first-party Schema Registry support for Avro, Protobuf, and JSON Schema. In ",[139,360,363],{"href":361,"rel":362},"https:\u002F\u002Fdocs.confluent.io\u002Fkafka-clients\u002Fpython\u002Fcurrent\u002Fchangelog.html",[275],"version 2.13",", Confluent removed the experimental module designation from its AsyncIO classes. They are newer than the synchronous APIs, and the batched async producer currently does not support per-message headers.",[10,366,367,368,373],{},"Confluent publishes ",[139,369,372],{"href":370,"rel":371},"https:\u002F\u002Fpypi.org\u002Fproject\u002Fconfluent-kafka\u002F",[275],"wheels"," for common CPython, Linux, macOS, and Windows combinations. Unsupported targets may require a source build, and the prebuilt Linux wheels omit Kerberos\u002FGSSAPI support. Test installation in the same container image and CPU architecture used in production.",[10,375,376],{},[170,377,378],{},"When to choose confluent-kafka",[10,380,381],{},"Start here for most new synchronous services, applications using Schema Registry, and teams that want commercial support. It is also the first candidate to benchmark for demanding throughput. Prefer another client when a universal pure-Python artifact is required or an established asyncio-native lifecycle matters more.",[332,383,23],{"id":23},[10,385,386,390,391,396],{},[139,387,23],{"href":388,"rel":389},"https:\u002F\u002Fkafka-python.readthedocs.io\u002Fen\u002Fstable\u002F",[275]," implements the Kafka protocol in Python and provides synchronous Producer, Consumer, and Admin APIs. The ",[139,392,395],{"href":393,"rel":394},"https:\u002F\u002Fkafka-python.readthedocs.io\u002Fen\u002Fstable\u002Fapidoc\u002FKafkaProducer.html",[275],"producer"," uses background threads for batching and network I\u002FO.",[10,398,399],{},[170,400,355],{},[10,402,403],{},"The 3.x line supports cooperative rebalancing, idempotent production, and transactions. It does not include Schema Registry integration, so using Avro, Protobuf, or JSON Schema requires an additional library.",[10,405,406,407,412],{},"The ",[139,408,411],{"href":409,"rel":410},"https:\u002F\u002Fpypi.org\u002Fproject\u002Fkafka-python\u002F",[275],"base package"," ships as a universal wheel and does not require a compiler or platform-specific native library. Optional CRC and compression packages may still contain native code.",[10,414,415],{},[170,416,417],{},"When to choose kafka-python",[10,419,420,421,423],{},"Choose ",[17,422,23],{}," when you prefer a synchronous client implemented in Python, want to choose serialization and Schema Registry tooling separately, or need a universal wheel without a native Kafka core.",[332,425,27],{"id":27},[10,427,428,432,433,437],{},[139,429,27],{"href":430,"rel":431},"https:\u002F\u002Faiokafka.readthedocs.io\u002Fen\u002Fstable\u002Findex.html",[275]," is an asyncio-native Kafka client. Starting, stopping, producing, and consuming use coroutines, and consumers support async iteration. Some of its protocol and error-handling code comes from ",[139,434,23],{"href":435,"rel":436},"https:\u002F\u002Fgithub.com\u002Fdpkp\u002Fkafka-python",[275],", but kafka-python is not installed as a dependency.",[10,439,440],{},[170,441,355],{},[10,443,444,445,450],{},"It includes the experimental ",[139,446,448],{"href":273,"rel":447},[275],[17,449,278],{}," for topic, configuration, partition, and consumer-group administration. It does not bundle a Schema Registry client, so schema serialization requires a separate library.",[10,452,453,454,456],{},"Applications must explicitly start and stop each ",[17,455,27],{}," producer and consumer. Blocking work must not run on the event loop, and shutdown must account for pending messages and offset commits.",[10,458,459,460,20,462,464,465,470],{},"Unlike ",[17,461,23],{},[17,463,27],{}," includes native code. ",[139,466,469],{"href":467,"rel":468},"https:\u002F\u002Fpypi.org\u002Fproject\u002Faiokafka\u002F",[275],"Prebuilt packages"," are available for common systems, but less common environments may not have one. Installing from source requires a C compiler.",[10,472,473],{},[170,474,475],{},"When to choose aiokafka",[10,477,420,478,480],{},[17,479,27],{}," when your application is built around asyncio and you want Kafka producing, consuming, and lifecycle management to use async and await throughout.",[30,482,484],{"id":483},"github-repository-metrics","GitHub repository metrics",[10,486,487],{},"The tables below compare the three clients' GitHub activity, maintenance, and public usage using the same metrics and assessment rules. Snapshot: 12 Aug 2026.",[332,489,491],{"id":490},"project-overview","Project overview",[35,493,494,506],{},[38,495,496],{},[41,497,498,500,502,504],{},[44,499],{},[44,501,19],{},[44,503,23],{},[44,505,27],{},[54,507,508,522,534],{},[41,509,510,513,516,519],{},[59,511,512],{},"Repository created",[59,514,515],{},"14 Apr 2016",[59,517,518],{},"24 Sep 2012",[59,520,521],{},"1 Nov 2014",[41,523,524,527,530,532],{},[59,525,526],{},"License",[59,528,529],{},"Apache-2.0",[59,531,529],{},[59,533,529],{},[41,535,536,539,542,544],{},[59,537,538],{},"Repository status",[59,540,541],{},"Active · original",[59,543,541],{},[59,545,541],{},[332,547,549],{"id":548},"activity","Activity",[35,551,552,565],{},[38,553,554],{},[41,555,556,559,561,563],{},[44,557,558],{},"Metric",[44,560,19],{},[44,562,23],{},[44,564,27],{},[54,566,567,581,595,609,623,637,651],{},[41,568,569,572,575,578],{},[59,570,571],{},"Latest default-branch commit",[59,573,574],{},"7 Aug 2026",[59,576,577],{},"4 Aug 2026",[59,579,580],{},"9 Aug 2026",[41,582,583,586,589,592],{},[59,584,585],{},"Latest GitHub Release",[59,587,588],{},"v2.15.0 (30 Jun 2026)",[59,590,591],{},"3.0.10 (4 Aug 2026)",[59,593,594],{},"v0.14.0 (29 Apr 2026)",[41,596,597,600,603,606],{},[59,598,599],{},"GitHub Releases (12 mo)",[59,601,602],{},"10",[59,604,605],{},"16",[59,607,608],{},"3",[41,610,611,614,617,620],{},[59,612,613],{},"Commits",[59,615,616],{},"44 (90 d) · 163 (12 mo)",[59,618,619],{},"171 (90 d) · 482 (12 mo)",[59,621,622],{},"3 (90 d) · 17 (12 mo)",[41,624,625,628,631,634],{},[59,626,627],{},"Issue flow (90 d)",[59,629,630],{},"11 opened · 8 closed",[59,632,633],{},"18 opened · 34 closed",[59,635,636],{},"4 opened · 1 closed",[41,638,639,642,645,648],{},[59,640,641],{},"PR flow (90 d)",[59,643,644],{},"64 opened · 45 merged",[59,646,647],{},"160 opened · 155 merged",[59,649,650],{},"8 opened · 3 merged",[41,652,653,656,659,662],{},[59,654,655],{},"Activity assessment",[59,657,658],{},"🟢 44 commits and 45 merged PRs in the last 90 days.",[59,660,661],{},"🟢 171 commits and 155 merged PRs in the last 90 days.",[59,663,664],{},"🟡 3 commits and 3 merged PRs in the last 90 days.",[10,666,667],{},"Release figures cover GitHub Releases, not PyPI.",[332,669,671],{"id":670},"maintenance","Maintenance",[35,673,674,686],{},[38,675,676],{},[41,677,678,680,682,684],{},[44,679,558],{},[44,681,19],{},[44,683,23],{},[44,685,27],{},[54,687,688,701,714,728,742,756,770,782,796],{},[41,689,690,693,696,698],{},[59,691,692],{},"Active commit authors (12 mo)",[59,694,695],{},"30",[59,697,602],{},[59,699,700],{},"4",[41,702,703,706,709,712],{},[59,704,705],{},"PR merge distribution (12 mo)",[59,707,708],{},"17 people · Top 1: 23% · Top 2: 43%",[59,710,711],{},"1 person · 100% of merges",[59,713,711],{},[41,715,716,719,722,725],{},[59,717,718],{},"Issue backlog",[59,720,721],{},"131 open · median age 2.9 y",[59,723,724],{},"16 open · median age 8.5 y",[59,726,727],{},"157 open · median age 3.3 y",[41,729,730,733,736,739],{},[59,731,732],{},"Issue closure rate",[59,734,735],{},"5\u002F12 closed within 30 d · 5\u002F12 within 90 d",[59,737,738],{},"3\u002F5 closed within 30 d · 4\u002F5 within 90 d",[59,740,741],{},"0\u002F2 closed within 30 d · 1\u002F2 within 90 d (small sample)",[41,743,744,747,750,753],{},[59,745,746],{},"PR backlog",[59,748,749],{},"85 open · median age 2.1 y",[59,751,752],{},"3 open · median age 4 d",[59,754,755],{},"32 open · median age 1.4 y",[41,757,758,761,764,767],{},[59,759,760],{},"Median PR merge time (90 d)",[59,762,763],{},"3.2 d (n=45)",[59,765,766],{},"1.1 h (n=155)",[59,768,769],{},"28.8 d (n=3 — small sample)",[41,771,772,775,778,780],{},[59,773,774],{},"Published GitHub security advisories",[59,776,777],{},"0",[59,779,777],{},[59,781,777],{},[41,783,784,787,790,793],{},[59,785,786],{},"Responsiveness assessment",[59,788,789],{},"🟡 New PRs merge in a median of 3.2 d (n=45), but 85 open PRs have a median age of 2.1 y.",[59,791,792],{},"🟢 New PRs merge in a median of 1.1 h (n=155); the median open PR age is 4 d, and 4 of 5 issues closed within 90 d.",[59,794,795],{},"🔴 Only 3 PRs merged in 90 d, while 32 open PRs have a median age of 1.4 y.",[41,797,798,801,804,807],{},[59,799,800],{},"PR merge concentration assessment",[59,802,803],{},"🟢 17 people merged PRs in 12 mo; the most active account handled 23% of merges.",[59,805,806],{},"🔴 1 person merged PRs in 12 mo and handled 100% of merges.",[59,808,806],{},[10,810,811,812,815],{},"PR merge distribution counts non-bot ",[17,813,814],{},"mergedBy"," accounts, so automated merges may undercount human reviewers. Issue closure rates use issues opened 90–180 days before the snapshot, giving each issue a full 90-day window.",[332,817,819],{"id":818},"public-usage-and-interest","Public usage and interest",[35,821,822,834],{},[38,823,824],{},[41,825,826,828,830,832],{},[44,827,558],{},[44,829,19],{},[44,831,23],{},[44,833,27],{},[54,835,836,850,864,878],{},[41,837,838,841,844,847],{},[59,839,840],{},"Stars",[59,842,843],{},"500",[59,845,846],{},"5,901",[59,848,849],{},"1,397",[41,851,852,855,858,861],{},[59,853,854],{},"Forks",[59,856,857],{},"956",[59,859,860],{},"1,470",[59,862,863],{},"267",[41,865,866,869,872,875],{},[59,867,868],{},"GitHub dependents (Used by)",[59,870,871],{},"17,009",[59,873,874],{},"36,189",[59,876,877],{},"7,236",[41,879,880,883,886,889],{},[59,881,882],{},"Public usage assessment",[59,884,885],{},"🟢 Strong public usage despite modest GitHub interest: 17,009 dependents, 956 forks, and 500 stars.",[59,887,888],{},"🟢 Strong public usage and interest: 36,189 dependents, 1,470 forks, and 5,901 stars.",[59,890,891],{},"🟡 Widely used in public repositories, with moderate GitHub interest: 7,236 dependents, 267 forks, and 1,397 stars.",[10,893,894],{},"GitHub dependents are approximate public-repository counts.",[332,896,898],{"id":897},"overall-repository-signals","Overall repository signals",[900,901,902,908,913],"ul",{},[903,904,905,907],"li",{},[170,906,19],{}," has the broadest contributor participation and strong public usage; recent PRs merge quickly, while the open-PR backlog is much older.",[903,909,910,912],{},[170,911,23],{}," has the highest public usage and recent activity; one account handled all recorded PR merges in the past year, and its open issues are old.",[903,914,915,917],{},[170,916,27],{}," remains widely used, but recent activity is lower and its issue and PR backlogs are old.",[30,919,921],{"id":920},"test-kafka-clients-with-kafma","Test Kafka clients with Kafma",[10,923,924],{},"Whichever client you choose, you still need to verify that your code behaves as expected. For a producer, check what Kafka actually received. For a consumer, publish a controlled message and confirm that your application handles it correctly.",[10,926,927,928,932],{},"We use ",[139,929,931],{"href":930},"\u002F","Kafma—the desktop Kafka UI"," for both tasks. It can inspect records produced by an application and publish test records without another temporary script.",[10,934,935,936,939,940,943,944,947],{},"Both tests use the ",[17,937,938],{},"kafka-client-test"," topic, the key ",[17,941,942],{},"u_10",", and the JSON value ",[17,945,946],{},"{\"event\":\"signup\",\"ts\":1767225600}",". Different headers identify which test produced each record.",[10,949,950,951,953,954,957,958,961,962,957,964,162],{},"The examples use ",[17,952,23],{}," to keep setup simple because its base package installs without a native Kafka library. In kafka-python 3.x, ",[17,955,956],{},"SerializeWrapper"," and ",[17,959,960],{},"DeserializeWrapper"," adapt the callable serializers used below. The same verification workflow applies to ",[17,963,19],{},[17,965,27],{},[332,967,969],{"id":968},"test-the-producer","Test the producer",[10,971,972,973,976,977,979],{},"This producer identifies its Kafka connection as ",[17,974,975],{},"kafma-blog-producer"," and the record itself as coming from ",[17,978,23],{},":",[981,982,987],"pre",{"className":983,"code":984,"language":985,"meta":986,"style":986},"language-python shiki shiki-themes kafma-dark","import json\n\nfrom kafka import KafkaProducer\nfrom kafka.serializer import SerializeWrapper\n\nbootstrap_servers = \"127.0.0.1:9092\"\nclient_id = \"kafma-blog-producer\"\ntopic = \"kafka-client-test\"\nkey = \"u_10\"\nvalue = {\"event\": \"signup\", \"ts\": 1767225600}\nheaders = [\n    (\"trace-id\", b\"p-u10-01\"),\n    (\"message-source\", b\"kafka-python\"),\n]\n\nproducer = KafkaProducer(\n    bootstrap_servers=bootstrap_servers,\n    client_id=client_id,\n    key_serializer=SerializeWrapper(lambda data: data.encode(\"utf-8\")),\n    value_serializer=SerializeWrapper(\n        lambda data: json.dumps(data).encode(\"utf-8\")\n    ),\n)\n\ntry:\n    result = producer.send(\n        topic,\n        key=key,\n        value=value,\n        headers=headers,\n        partition=0,\n    ).get(timeout=10)\n\n    print(\"Sent a kafka-python test record:\")\n    print(f\"Client ID: {client_id}\")\n    print(f\"Topic: {topic}\")\n    print(f\"Partition: {result.partition}\")\n    print(f\"Offset: {result.offset}\")\n    print(f\"Key: {key}\")\n    print(f\"Value: {json.dumps(value)}\")\n    print(\"Headers:\")\n    for name, header_value in headers:\n        print(f\"  {name}: {header_value.decode('utf-8')}\")\nfinally:\n    producer.close()\n","python","",[17,988,989,1002,1009,1023,1041,1046,1059,1070,1081,1092,1125,1136,1156,1173,1179,1184,1198,1212,1225,1259,1271,1306,1312,1317,1322,1328,1346,1354,1367,1380,1393,1405,1425,1430,1444,1470,1493,1521,1548,1570,1603,1615,1638,1684,1690],{"__ignoreMap":986},[990,991,994,998],"span",{"class":992,"line":993},"line",1,[990,995,997],{"class":996},"sifj9","import",[990,999,1001],{"class":1000},"sUqoa"," json\n",[990,1003,1005],{"class":992,"line":1004},2,[990,1006,1008],{"emptyLinePlaceholder":1007},true,"\n",[990,1010,1012,1015,1018,1020],{"class":992,"line":1011},3,[990,1013,1014],{"class":996},"from",[990,1016,1017],{"class":1000}," kafka ",[990,1019,997],{"class":996},[990,1021,1022],{"class":1000}," KafkaProducer\n",[990,1024,1026,1028,1031,1033,1036,1038],{"class":992,"line":1025},4,[990,1027,1014],{"class":996},[990,1029,1030],{"class":1000}," kafka",[990,1032,162],{"class":996},[990,1034,1035],{"class":1000},"serializer ",[990,1037,997],{"class":996},[990,1039,1040],{"class":1000}," SerializeWrapper\n",[990,1042,1044],{"class":992,"line":1043},5,[990,1045,1008],{"emptyLinePlaceholder":1007},[990,1047,1049,1052,1055],{"class":992,"line":1048},6,[990,1050,1051],{"class":1000},"bootstrap_servers ",[990,1053,1054],{"class":996},"=",[990,1056,1058],{"class":1057},"sJl8Q"," \"127.0.0.1:9092\"\n",[990,1060,1062,1065,1067],{"class":992,"line":1061},7,[990,1063,1064],{"class":1000},"client_id ",[990,1066,1054],{"class":996},[990,1068,1069],{"class":1057}," \"kafma-blog-producer\"\n",[990,1071,1073,1076,1078],{"class":992,"line":1072},8,[990,1074,1075],{"class":1000},"topic ",[990,1077,1054],{"class":996},[990,1079,1080],{"class":1057}," \"kafka-client-test\"\n",[990,1082,1084,1087,1089],{"class":992,"line":1083},9,[990,1085,1086],{"class":1000},"key ",[990,1088,1054],{"class":996},[990,1090,1091],{"class":1057}," \"u_10\"\n",[990,1093,1095,1098,1100,1103,1106,1108,1111,1114,1117,1119,1122],{"class":992,"line":1094},10,[990,1096,1097],{"class":1000},"value ",[990,1099,1054],{"class":996},[990,1101,1102],{"class":996}," {",[990,1104,1105],{"class":1057},"\"event\"",[990,1107,979],{"class":996},[990,1109,1110],{"class":1057}," \"signup\"",[990,1112,1113],{"class":996},",",[990,1115,1116],{"class":1057}," \"ts\"",[990,1118,979],{"class":996},[990,1120,1121],{"class":1057}," 1767225600",[990,1123,1124],{"class":996},"}\n",[990,1126,1128,1131,1133],{"class":992,"line":1127},11,[990,1129,1130],{"class":1000},"headers ",[990,1132,1054],{"class":996},[990,1134,1135],{"class":996}," [\n",[990,1137,1139,1142,1145,1147,1150,1153],{"class":992,"line":1138},12,[990,1140,1141],{"class":996},"    (",[990,1143,1144],{"class":1057},"\"trace-id\"",[990,1146,1113],{"class":996},[990,1148,1149],{"class":996}," b",[990,1151,1152],{"class":1057},"\"p-u10-01\"",[990,1154,1155],{"class":996},"),\n",[990,1157,1159,1161,1164,1166,1168,1171],{"class":992,"line":1158},13,[990,1160,1141],{"class":996},[990,1162,1163],{"class":1057},"\"message-source\"",[990,1165,1113],{"class":996},[990,1167,1149],{"class":996},[990,1169,1170],{"class":1057},"\"kafka-python\"",[990,1172,1155],{"class":996},[990,1174,1176],{"class":992,"line":1175},14,[990,1177,1178],{"class":996},"]\n",[990,1180,1182],{"class":992,"line":1181},15,[990,1183,1008],{"emptyLinePlaceholder":1007},[990,1185,1187,1190,1192,1195],{"class":992,"line":1186},16,[990,1188,1189],{"class":1000},"producer ",[990,1191,1054],{"class":996},[990,1193,1194],{"class":1000}," KafkaProducer",[990,1196,1197],{"class":996},"(\n",[990,1199,1201,1204,1206,1209],{"class":992,"line":1200},17,[990,1202,1203],{"class":1000},"    bootstrap_servers",[990,1205,1054],{"class":996},[990,1207,1208],{"class":1000},"bootstrap_servers",[990,1210,1211],{"class":996},",\n",[990,1213,1215,1218,1220,1223],{"class":992,"line":1214},18,[990,1216,1217],{"class":1000},"    client_id",[990,1219,1054],{"class":996},[990,1221,1222],{"class":1000},"client_id",[990,1224,1211],{"class":996},[990,1226,1228,1231,1233,1235,1238,1241,1243,1245,1247,1250,1253,1256],{"class":992,"line":1227},19,[990,1229,1230],{"class":1000},"    key_serializer",[990,1232,1054],{"class":996},[990,1234,956],{"class":1000},[990,1236,1237],{"class":996},"(lambda",[990,1239,1240],{"class":1000}," data",[990,1242,979],{"class":996},[990,1244,1240],{"class":1000},[990,1246,162],{"class":996},[990,1248,1249],{"class":1000},"encode",[990,1251,1252],{"class":996},"(",[990,1254,1255],{"class":1057},"\"utf-8\"",[990,1257,1258],{"class":996},")),\n",[990,1260,1262,1265,1267,1269],{"class":992,"line":1261},20,[990,1263,1264],{"class":1000},"    value_serializer",[990,1266,1054],{"class":996},[990,1268,956],{"class":1000},[990,1270,1197],{"class":996},[990,1272,1274,1277,1279,1281,1284,1286,1289,1291,1294,1297,1299,1301,1303],{"class":992,"line":1273},21,[990,1275,1276],{"class":996},"        lambda",[990,1278,1240],{"class":1000},[990,1280,979],{"class":996},[990,1282,1283],{"class":1000}," json",[990,1285,162],{"class":996},[990,1287,1288],{"class":1000},"dumps",[990,1290,1252],{"class":996},[990,1292,1293],{"class":1000},"data",[990,1295,1296],{"class":996},").",[990,1298,1249],{"class":1000},[990,1300,1252],{"class":996},[990,1302,1255],{"class":1057},[990,1304,1305],{"class":996},")\n",[990,1307,1309],{"class":992,"line":1308},22,[990,1310,1311],{"class":996},"    ),\n",[990,1313,1315],{"class":992,"line":1314},23,[990,1316,1305],{"class":996},[990,1318,1320],{"class":992,"line":1319},24,[990,1321,1008],{"emptyLinePlaceholder":1007},[990,1323,1325],{"class":992,"line":1324},25,[990,1326,1327],{"class":996},"try:\n",[990,1329,1331,1334,1336,1339,1341,1344],{"class":992,"line":1330},26,[990,1332,1333],{"class":1000},"    result ",[990,1335,1054],{"class":996},[990,1337,1338],{"class":1000}," producer",[990,1340,162],{"class":996},[990,1342,1343],{"class":1000},"send",[990,1345,1197],{"class":996},[990,1347,1349,1352],{"class":992,"line":1348},27,[990,1350,1351],{"class":1000},"        topic",[990,1353,1211],{"class":996},[990,1355,1357,1360,1362,1365],{"class":992,"line":1356},28,[990,1358,1359],{"class":1000},"        key",[990,1361,1054],{"class":996},[990,1363,1364],{"class":1000},"key",[990,1366,1211],{"class":996},[990,1368,1370,1373,1375,1378],{"class":992,"line":1369},29,[990,1371,1372],{"class":1000},"        value",[990,1374,1054],{"class":996},[990,1376,1377],{"class":1000},"value",[990,1379,1211],{"class":996},[990,1381,1383,1386,1388,1391],{"class":992,"line":1382},30,[990,1384,1385],{"class":1000},"        headers",[990,1387,1054],{"class":996},[990,1389,1390],{"class":1000},"headers",[990,1392,1211],{"class":996},[990,1394,1396,1399,1401,1403],{"class":992,"line":1395},31,[990,1397,1398],{"class":1000},"        partition",[990,1400,1054],{"class":996},[990,1402,777],{"class":1057},[990,1404,1211],{"class":996},[990,1406,1408,1411,1414,1416,1419,1421,1423],{"class":992,"line":1407},32,[990,1409,1410],{"class":996},"    ).",[990,1412,1413],{"class":1000},"get",[990,1415,1252],{"class":996},[990,1417,1418],{"class":1000},"timeout",[990,1420,1054],{"class":996},[990,1422,602],{"class":1057},[990,1424,1305],{"class":996},[990,1426,1428],{"class":992,"line":1427},33,[990,1429,1008],{"emptyLinePlaceholder":1007},[990,1431,1433,1437,1439,1442],{"class":992,"line":1432},34,[990,1434,1436],{"class":1435},"sLaUg","    print",[990,1438,1252],{"class":996},[990,1440,1441],{"class":1057},"\"Sent a kafka-python test record:\"",[990,1443,1305],{"class":996},[990,1445,1447,1449,1451,1454,1457,1460,1462,1465,1468],{"class":992,"line":1446},35,[990,1448,1436],{"class":1435},[990,1450,1252],{"class":996},[990,1452,1453],{"class":996},"f",[990,1455,1456],{"class":1057},"\"Client ID: ",[990,1458,1459],{"class":1057},"{",[990,1461,1222],{"class":1000},[990,1463,1464],{"class":1057},"}",[990,1466,1467],{"class":1057},"\"",[990,1469,1305],{"class":996},[990,1471,1473,1475,1477,1479,1482,1484,1487,1489,1491],{"class":992,"line":1472},36,[990,1474,1436],{"class":1435},[990,1476,1252],{"class":996},[990,1478,1453],{"class":996},[990,1480,1481],{"class":1057},"\"Topic: ",[990,1483,1459],{"class":1057},[990,1485,1486],{"class":1000},"topic",[990,1488,1464],{"class":1057},[990,1490,1467],{"class":1057},[990,1492,1305],{"class":996},[990,1494,1496,1498,1500,1502,1505,1507,1510,1512,1515,1517,1519],{"class":992,"line":1495},37,[990,1497,1436],{"class":1435},[990,1499,1252],{"class":996},[990,1501,1453],{"class":996},[990,1503,1504],{"class":1057},"\"Partition: ",[990,1506,1459],{"class":1057},[990,1508,1509],{"class":1000},"result",[990,1511,162],{"class":996},[990,1513,1514],{"class":1000},"partition",[990,1516,1464],{"class":1057},[990,1518,1467],{"class":1057},[990,1520,1305],{"class":996},[990,1522,1524,1526,1528,1530,1533,1535,1537,1539,1542,1544,1546],{"class":992,"line":1523},38,[990,1525,1436],{"class":1435},[990,1527,1252],{"class":996},[990,1529,1453],{"class":996},[990,1531,1532],{"class":1057},"\"Offset: ",[990,1534,1459],{"class":1057},[990,1536,1509],{"class":1000},[990,1538,162],{"class":996},[990,1540,1541],{"class":1000},"offset",[990,1543,1464],{"class":1057},[990,1545,1467],{"class":1057},[990,1547,1305],{"class":996},[990,1549,1551,1553,1555,1557,1560,1562,1564,1566,1568],{"class":992,"line":1550},39,[990,1552,1436],{"class":1435},[990,1554,1252],{"class":996},[990,1556,1453],{"class":996},[990,1558,1559],{"class":1057},"\"Key: ",[990,1561,1459],{"class":1057},[990,1563,1364],{"class":1000},[990,1565,1464],{"class":1057},[990,1567,1467],{"class":1057},[990,1569,1305],{"class":996},[990,1571,1573,1575,1577,1579,1582,1584,1587,1589,1591,1593,1595,1597,1599,1601],{"class":992,"line":1572},40,[990,1574,1436],{"class":1435},[990,1576,1252],{"class":996},[990,1578,1453],{"class":996},[990,1580,1581],{"class":1057},"\"Value: ",[990,1583,1459],{"class":1057},[990,1585,1586],{"class":1000},"json",[990,1588,162],{"class":996},[990,1590,1288],{"class":1000},[990,1592,1252],{"class":996},[990,1594,1377],{"class":1000},[990,1596,219],{"class":996},[990,1598,1464],{"class":1057},[990,1600,1467],{"class":1057},[990,1602,1305],{"class":996},[990,1604,1606,1608,1610,1613],{"class":992,"line":1605},41,[990,1607,1436],{"class":1435},[990,1609,1252],{"class":996},[990,1611,1612],{"class":1057},"\"Headers:\"",[990,1614,1305],{"class":996},[990,1616,1618,1621,1624,1626,1629,1632,1635],{"class":992,"line":1617},42,[990,1619,1620],{"class":996},"    for",[990,1622,1623],{"class":1000}," name",[990,1625,1113],{"class":996},[990,1627,1628],{"class":1000}," header_value ",[990,1630,1631],{"class":996},"in",[990,1633,1634],{"class":1000}," headers",[990,1636,1637],{"class":996},":\n",[990,1639,1641,1644,1646,1648,1651,1653,1656,1658,1661,1663,1666,1668,1671,1673,1676,1678,1680,1682],{"class":992,"line":1640},43,[990,1642,1643],{"class":1435},"        print",[990,1645,1252],{"class":996},[990,1647,1453],{"class":996},[990,1649,1650],{"class":1057},"\"  ",[990,1652,1459],{"class":1057},[990,1654,1655],{"class":1000},"name",[990,1657,1464],{"class":1057},[990,1659,1660],{"class":1057},": ",[990,1662,1459],{"class":1057},[990,1664,1665],{"class":1000},"header_value",[990,1667,162],{"class":996},[990,1669,1670],{"class":1000},"decode",[990,1672,1252],{"class":996},[990,1674,1675],{"class":1057},"'utf-8'",[990,1677,219],{"class":996},[990,1679,1464],{"class":1057},[990,1681,1467],{"class":1057},[990,1683,1305],{"class":996},[990,1685,1687],{"class":992,"line":1686},44,[990,1688,1689],{"class":996},"finally:\n",[990,1691,1693,1696,1698,1701],{"class":992,"line":1692},45,[990,1694,1695],{"class":1000},"    producer",[990,1697,162],{"class":996},[990,1699,1700],{"class":1000},"close",[990,1702,1703],{"class":996},"()\n",[10,1705,1706],{},[1707,1708],"img",{"alt":1709,"height":1710,"src":1711,"width":1712},"kafka-python producer reporting the test message sent to kafka-client-test",388,"https:\u002F\u002Fmedia.kafma.app\u002Fblog\u002Fkafka-python-clients\u002Fpython-producer.png",908,[10,1714,1715,1716,1718,1719,1721],{},"Open ",[17,1717,938],{}," in Kafma and confirm that partition ",[17,1720,777],{}," contains the expected key, JSON value, and both headers.",[10,1723,1724],{},[1707,1725],{"alt":1726,"height":1727,"src":1728,"width":1729},"Kafma Kafka UI showing the test message key, decoded JSON value, headers, partition, and offset",1520,"https:\u002F\u002Fmedia.kafma.app\u002Fblog\u002Fkafka-python-clients\u002Fkafma-viewer.png",2160,[332,1731,1733],{"id":1732},"test-the-consumer","Test the consumer",[10,1735,1736,1737,1740,1741,979],{},"Start the consumer, then publish a record from Kafma with the ",[17,1738,1739],{},"message-source"," header set to ",[17,1742,1743],{},"kafma",[981,1745,1747],{"className":983,"code":1746,"language":985,"meta":986,"style":986},"import json\n\nfrom kafka import KafkaConsumer\nfrom kafka.serializer import DeserializeWrapper\n\nconsumer = KafkaConsumer(\n    \"kafka-client-test\",\n    bootstrap_servers=\"127.0.0.1:9092\",\n    client_id=\"kafma-blog-consumer\",\n    group_id=\"kafma-blog-consumer-test\",\n    auto_offset_reset=\"latest\",\n    enable_auto_commit=False,\n    consumer_timeout_ms=30_000,\n    key_deserializer=DeserializeWrapper(lambda data: data.decode(\"utf-8\")),\n    value_deserializer=DeserializeWrapper(\n        lambda data: json.loads(data.decode(\"utf-8\"))\n    ),\n)\n\ntry:\n    for _ in range(30):\n        consumer.poll(timeout_ms=1_000)\n        if consumer.assignment():\n            break\n    else:\n        raise TimeoutError(\"Consumer did not receive a partition within 30 seconds\")\n\n    print(\"Ready for the Kafma test record\")\n\n    for record in consumer:\n        headers = dict(record.headers)\n        if headers.get(\"message-source\") != b\"kafma\":\n            continue\n\n        print(\"Received a Kafma test record\")\n        print(\"Client ID: kafma-blog-consumer\")\n        print(f\"Topic: {record.topic}\")\n        print(f\"Partition: {record.partition}\")\n        print(f\"Offset: {record.offset}\")\n        print(f\"Key: {record.key}\")\n        print(f\"Value: {json.dumps(record.value, separators=(',', ':'))}\")\n        print(\"Headers:\")\n        for name, header_value in record.headers:\n            print(f\"  {name}: {header_value.decode('utf-8')}\")\n        break\n    else:\n        raise TimeoutError(\"No Kafma test record received within 30 seconds\")\nfinally:\n    consumer.close()\n",[17,1748,1749,1755,1759,1770,1785,1789,1801,1808,1819,1830,1842,1854,1866,1878,1905,1916,1946,1950,1954,1958,1962,1981,2003,2019,2024,2029,2044,2048,2059,2063,2076,2097,2123,2128,2132,2143,2154,2178,2202,2226,2250,2301,2311,2333,2372,2377,2382,2396,2401],{"__ignoreMap":986},[990,1750,1751,1753],{"class":992,"line":993},[990,1752,997],{"class":996},[990,1754,1001],{"class":1000},[990,1756,1757],{"class":992,"line":1004},[990,1758,1008],{"emptyLinePlaceholder":1007},[990,1760,1761,1763,1765,1767],{"class":992,"line":1011},[990,1762,1014],{"class":996},[990,1764,1017],{"class":1000},[990,1766,997],{"class":996},[990,1768,1769],{"class":1000}," KafkaConsumer\n",[990,1771,1772,1774,1776,1778,1780,1782],{"class":992,"line":1025},[990,1773,1014],{"class":996},[990,1775,1030],{"class":1000},[990,1777,162],{"class":996},[990,1779,1035],{"class":1000},[990,1781,997],{"class":996},[990,1783,1784],{"class":1000}," DeserializeWrapper\n",[990,1786,1787],{"class":992,"line":1043},[990,1788,1008],{"emptyLinePlaceholder":1007},[990,1790,1791,1794,1796,1799],{"class":992,"line":1048},[990,1792,1793],{"class":1000},"consumer ",[990,1795,1054],{"class":996},[990,1797,1798],{"class":1000}," KafkaConsumer",[990,1800,1197],{"class":996},[990,1802,1803,1806],{"class":992,"line":1061},[990,1804,1805],{"class":1057},"    \"kafka-client-test\"",[990,1807,1211],{"class":996},[990,1809,1810,1812,1814,1817],{"class":992,"line":1072},[990,1811,1203],{"class":1000},[990,1813,1054],{"class":996},[990,1815,1816],{"class":1057},"\"127.0.0.1:9092\"",[990,1818,1211],{"class":996},[990,1820,1821,1823,1825,1828],{"class":992,"line":1083},[990,1822,1217],{"class":1000},[990,1824,1054],{"class":996},[990,1826,1827],{"class":1057},"\"kafma-blog-consumer\"",[990,1829,1211],{"class":996},[990,1831,1832,1835,1837,1840],{"class":992,"line":1094},[990,1833,1834],{"class":1000},"    group_id",[990,1836,1054],{"class":996},[990,1838,1839],{"class":1057},"\"kafma-blog-consumer-test\"",[990,1841,1211],{"class":996},[990,1843,1844,1847,1849,1852],{"class":992,"line":1127},[990,1845,1846],{"class":1000},"    auto_offset_reset",[990,1848,1054],{"class":996},[990,1850,1851],{"class":1057},"\"latest\"",[990,1853,1211],{"class":996},[990,1855,1856,1859,1861,1864],{"class":992,"line":1138},[990,1857,1858],{"class":1000},"    enable_auto_commit",[990,1860,1054],{"class":996},[990,1862,1863],{"class":1057},"False",[990,1865,1211],{"class":996},[990,1867,1868,1871,1873,1876],{"class":992,"line":1158},[990,1869,1870],{"class":1000},"    consumer_timeout_ms",[990,1872,1054],{"class":996},[990,1874,1875],{"class":1057},"30_000",[990,1877,1211],{"class":996},[990,1879,1880,1883,1885,1887,1889,1891,1893,1895,1897,1899,1901,1903],{"class":992,"line":1175},[990,1881,1882],{"class":1000},"    key_deserializer",[990,1884,1054],{"class":996},[990,1886,960],{"class":1000},[990,1888,1237],{"class":996},[990,1890,1240],{"class":1000},[990,1892,979],{"class":996},[990,1894,1240],{"class":1000},[990,1896,162],{"class":996},[990,1898,1670],{"class":1000},[990,1900,1252],{"class":996},[990,1902,1255],{"class":1057},[990,1904,1258],{"class":996},[990,1906,1907,1910,1912,1914],{"class":992,"line":1181},[990,1908,1909],{"class":1000},"    value_deserializer",[990,1911,1054],{"class":996},[990,1913,960],{"class":1000},[990,1915,1197],{"class":996},[990,1917,1918,1920,1922,1924,1926,1928,1931,1933,1935,1937,1939,1941,1943],{"class":992,"line":1186},[990,1919,1276],{"class":996},[990,1921,1240],{"class":1000},[990,1923,979],{"class":996},[990,1925,1283],{"class":1000},[990,1927,162],{"class":996},[990,1929,1930],{"class":1000},"loads",[990,1932,1252],{"class":996},[990,1934,1293],{"class":1000},[990,1936,162],{"class":996},[990,1938,1670],{"class":1000},[990,1940,1252],{"class":996},[990,1942,1255],{"class":1057},[990,1944,1945],{"class":996},"))\n",[990,1947,1948],{"class":992,"line":1200},[990,1949,1311],{"class":996},[990,1951,1952],{"class":992,"line":1214},[990,1953,1305],{"class":996},[990,1955,1956],{"class":992,"line":1227},[990,1957,1008],{"emptyLinePlaceholder":1007},[990,1959,1960],{"class":992,"line":1261},[990,1961,1327],{"class":996},[990,1963,1964,1966,1969,1971,1974,1976,1978],{"class":992,"line":1273},[990,1965,1620],{"class":996},[990,1967,1968],{"class":1000}," _ ",[990,1970,1631],{"class":996},[990,1972,1973],{"class":1435}," range",[990,1975,1252],{"class":996},[990,1977,695],{"class":1057},[990,1979,1980],{"class":996},"):\n",[990,1982,1983,1986,1988,1991,1993,1996,1998,2001],{"class":992,"line":1308},[990,1984,1985],{"class":1000},"        consumer",[990,1987,162],{"class":996},[990,1989,1990],{"class":1000},"poll",[990,1992,1252],{"class":996},[990,1994,1995],{"class":1000},"timeout_ms",[990,1997,1054],{"class":996},[990,1999,2000],{"class":1057},"1_000",[990,2002,1305],{"class":996},[990,2004,2005,2008,2011,2013,2016],{"class":992,"line":1314},[990,2006,2007],{"class":996},"        if",[990,2009,2010],{"class":1000}," consumer",[990,2012,162],{"class":996},[990,2014,2015],{"class":1000},"assignment",[990,2017,2018],{"class":996},"():\n",[990,2020,2021],{"class":992,"line":1319},[990,2022,2023],{"class":996},"            break\n",[990,2025,2026],{"class":992,"line":1324},[990,2027,2028],{"class":996},"    else:\n",[990,2030,2031,2034,2037,2039,2042],{"class":992,"line":1330},[990,2032,2033],{"class":996},"        raise",[990,2035,2036],{"class":1435}," TimeoutError",[990,2038,1252],{"class":996},[990,2040,2041],{"class":1057},"\"Consumer did not receive a partition within 30 seconds\"",[990,2043,1305],{"class":996},[990,2045,2046],{"class":992,"line":1348},[990,2047,1008],{"emptyLinePlaceholder":1007},[990,2049,2050,2052,2054,2057],{"class":992,"line":1356},[990,2051,1436],{"class":1435},[990,2053,1252],{"class":996},[990,2055,2056],{"class":1057},"\"Ready for the Kafma test record\"",[990,2058,1305],{"class":996},[990,2060,2061],{"class":992,"line":1369},[990,2062,1008],{"emptyLinePlaceholder":1007},[990,2064,2065,2067,2070,2072,2074],{"class":992,"line":1382},[990,2066,1620],{"class":996},[990,2068,2069],{"class":1000}," record ",[990,2071,1631],{"class":996},[990,2073,2010],{"class":1000},[990,2075,1637],{"class":996},[990,2077,2078,2081,2083,2086,2088,2091,2093,2095],{"class":992,"line":1395},[990,2079,2080],{"class":1000},"        headers ",[990,2082,1054],{"class":996},[990,2084,2085],{"class":1435}," dict",[990,2087,1252],{"class":996},[990,2089,2090],{"class":1000},"record",[990,2092,162],{"class":996},[990,2094,1390],{"class":1000},[990,2096,1305],{"class":996},[990,2098,2099,2101,2103,2105,2107,2109,2111,2113,2116,2118,2121],{"class":992,"line":1407},[990,2100,2007],{"class":996},[990,2102,1634],{"class":1000},[990,2104,162],{"class":996},[990,2106,1413],{"class":1000},[990,2108,1252],{"class":996},[990,2110,1163],{"class":1057},[990,2112,219],{"class":996},[990,2114,2115],{"class":996}," !=",[990,2117,1149],{"class":996},[990,2119,2120],{"class":1057},"\"kafma\"",[990,2122,1637],{"class":996},[990,2124,2125],{"class":992,"line":1427},[990,2126,2127],{"class":996},"            continue\n",[990,2129,2130],{"class":992,"line":1432},[990,2131,1008],{"emptyLinePlaceholder":1007},[990,2133,2134,2136,2138,2141],{"class":992,"line":1446},[990,2135,1643],{"class":1435},[990,2137,1252],{"class":996},[990,2139,2140],{"class":1057},"\"Received a Kafma test record\"",[990,2142,1305],{"class":996},[990,2144,2145,2147,2149,2152],{"class":992,"line":1472},[990,2146,1643],{"class":1435},[990,2148,1252],{"class":996},[990,2150,2151],{"class":1057},"\"Client ID: kafma-blog-consumer\"",[990,2153,1305],{"class":996},[990,2155,2156,2158,2160,2162,2164,2166,2168,2170,2172,2174,2176],{"class":992,"line":1495},[990,2157,1643],{"class":1435},[990,2159,1252],{"class":996},[990,2161,1453],{"class":996},[990,2163,1481],{"class":1057},[990,2165,1459],{"class":1057},[990,2167,2090],{"class":1000},[990,2169,162],{"class":996},[990,2171,1486],{"class":1000},[990,2173,1464],{"class":1057},[990,2175,1467],{"class":1057},[990,2177,1305],{"class":996},[990,2179,2180,2182,2184,2186,2188,2190,2192,2194,2196,2198,2200],{"class":992,"line":1523},[990,2181,1643],{"class":1435},[990,2183,1252],{"class":996},[990,2185,1453],{"class":996},[990,2187,1504],{"class":1057},[990,2189,1459],{"class":1057},[990,2191,2090],{"class":1000},[990,2193,162],{"class":996},[990,2195,1514],{"class":1000},[990,2197,1464],{"class":1057},[990,2199,1467],{"class":1057},[990,2201,1305],{"class":996},[990,2203,2204,2206,2208,2210,2212,2214,2216,2218,2220,2222,2224],{"class":992,"line":1550},[990,2205,1643],{"class":1435},[990,2207,1252],{"class":996},[990,2209,1453],{"class":996},[990,2211,1532],{"class":1057},[990,2213,1459],{"class":1057},[990,2215,2090],{"class":1000},[990,2217,162],{"class":996},[990,2219,1541],{"class":1000},[990,2221,1464],{"class":1057},[990,2223,1467],{"class":1057},[990,2225,1305],{"class":996},[990,2227,2228,2230,2232,2234,2236,2238,2240,2242,2244,2246,2248],{"class":992,"line":1572},[990,2229,1643],{"class":1435},[990,2231,1252],{"class":996},[990,2233,1453],{"class":996},[990,2235,1559],{"class":1057},[990,2237,1459],{"class":1057},[990,2239,2090],{"class":1000},[990,2241,162],{"class":996},[990,2243,1364],{"class":1000},[990,2245,1464],{"class":1057},[990,2247,1467],{"class":1057},[990,2249,1305],{"class":996},[990,2251,2252,2254,2256,2258,2260,2262,2264,2266,2268,2270,2272,2274,2276,2278,2281,2284,2287,2289,2292,2295,2297,2299],{"class":992,"line":1605},[990,2253,1643],{"class":1435},[990,2255,1252],{"class":996},[990,2257,1453],{"class":996},[990,2259,1581],{"class":1057},[990,2261,1459],{"class":1057},[990,2263,1586],{"class":1000},[990,2265,162],{"class":996},[990,2267,1288],{"class":1000},[990,2269,1252],{"class":996},[990,2271,2090],{"class":1000},[990,2273,162],{"class":996},[990,2275,1377],{"class":1000},[990,2277,1113],{"class":996},[990,2279,2280],{"class":1000}," separators",[990,2282,2283],{"class":996},"=(",[990,2285,2286],{"class":1057},"','",[990,2288,1113],{"class":996},[990,2290,2291],{"class":1057}," ':'",[990,2293,2294],{"class":996},"))",[990,2296,1464],{"class":1057},[990,2298,1467],{"class":1057},[990,2300,1305],{"class":996},[990,2302,2303,2305,2307,2309],{"class":992,"line":1617},[990,2304,1643],{"class":1435},[990,2306,1252],{"class":996},[990,2308,1612],{"class":1057},[990,2310,1305],{"class":996},[990,2312,2313,2316,2318,2320,2322,2324,2327,2329,2331],{"class":992,"line":1640},[990,2314,2315],{"class":996},"        for",[990,2317,1623],{"class":1000},[990,2319,1113],{"class":996},[990,2321,1628],{"class":1000},[990,2323,1631],{"class":996},[990,2325,2326],{"class":1000}," record",[990,2328,162],{"class":996},[990,2330,1390],{"class":1000},[990,2332,1637],{"class":996},[990,2334,2335,2338,2340,2342,2344,2346,2348,2350,2352,2354,2356,2358,2360,2362,2364,2366,2368,2370],{"class":992,"line":1686},[990,2336,2337],{"class":1435},"            print",[990,2339,1252],{"class":996},[990,2341,1453],{"class":996},[990,2343,1650],{"class":1057},[990,2345,1459],{"class":1057},[990,2347,1655],{"class":1000},[990,2349,1464],{"class":1057},[990,2351,1660],{"class":1057},[990,2353,1459],{"class":1057},[990,2355,1665],{"class":1000},[990,2357,162],{"class":996},[990,2359,1670],{"class":1000},[990,2361,1252],{"class":996},[990,2363,1675],{"class":1057},[990,2365,219],{"class":996},[990,2367,1464],{"class":1057},[990,2369,1467],{"class":1057},[990,2371,1305],{"class":996},[990,2373,2374],{"class":992,"line":1692},[990,2375,2376],{"class":996},"        break\n",[990,2378,2380],{"class":992,"line":2379},46,[990,2381,2028],{"class":996},[990,2383,2385,2387,2389,2391,2394],{"class":992,"line":2384},47,[990,2386,2033],{"class":996},[990,2388,2036],{"class":1435},[990,2390,1252],{"class":996},[990,2392,2393],{"class":1057},"\"No Kafma test record received within 30 seconds\"",[990,2395,1305],{"class":996},[990,2397,2399],{"class":992,"line":2398},48,[990,2400,1689],{"class":996},[990,2402,2404,2407,2409,2411],{"class":992,"line":2403},49,[990,2405,2406],{"class":1000},"    consumer",[990,2408,162],{"class":996},[990,2410,1700],{"class":1000},[990,2412,1703],{"class":996},[10,2414,2415,2416,2418,2419,2421,2422,2424],{},"In Kafma, publish to partition ",[17,2417,777],{}," with key ",[17,2420,942],{},", value ",[17,2423,946],{},", and these headers:",[900,2426,2427,2435],{},[903,2428,2429,1660,2432],{},[17,2430,2431],{},"trace-id",[17,2433,2434],{},"c-u10-01",[903,2436,2437,1660,2439],{},[17,2438,1739],{},[17,2440,1743],{},[10,2442,2443],{},[1707,2444],{"alt":2445,"height":1727,"src":2446,"width":1729},"Kafma Kafka UI publishing the consumer test record to kafka-client-test","https:\u002F\u002Fmedia.kafma.app\u002Fblog\u002Fkafka-python-clients\u002Fkafma-producer.png",[10,2448,2449],{},"The Python consumer receives the record published by Kafma:",[10,2451,2452],{},[1707,2453],{"alt":2454,"height":2455,"src":2456,"width":2457},"kafka-python consumer reporting the test record received from Kafma",426,"https:\u002F\u002Fmedia.kafma.app\u002Fblog\u002Fkafka-python-clients\u002Fpython-viewer.png",910,[30,2459,2461],{"id":2460},"migrating-between-kafka-clients","Migrating between Kafka clients",[10,2463,2464],{},"Replacing a Kafka client means changing an application's Kafka integration, not moving records between brokers. Configuration names can be mapped mechanically, but the delivery, offset, rebalance, and shutdown behavior your application relies on must be verified. Migrate only when a concrete requirement justifies the work: a supported Python or broker version, a universal wheel, Schema Registry serializers, an asyncio-native lifecycle, or a commercial support policy.",[10,2466,2467],{},"Build the new integration beside the old one, then verify:",[900,2469,2470,2473,2476,2479,2482,2485],{},[903,2471,2472],{},"serialized keys, values, and headers using the Kafma checks above;",[903,2474,2475],{},"acknowledgements, retries, idempotence, delivery results, and flush behavior;",[903,2477,2478],{},"offset commit timing and failures after a record is read;",[903,2480,2481],{},"partition revocation and commits during rebalancing;",[903,2483,2484],{},"shutdown while records or handlers remain in flight;",[903,2486,2487],{},"authentication, compression, and Schema Registry behavior in the production environment.",[10,2489,2490],{},"Run the old and new producers against a separate test topic, or route a controlled share of consumers to the new implementation. Compare broker-visible records and application outcomes before removing the old client. Do not run both consumers in the same group expecting each one to receive every record; Kafka divides partitions across group members.",[10,2492,2493],{},"Moving between synchronous clients mainly changes APIs and operational behavior. Moving between synchronous and asyncio-native clients also changes how the application handles startup, shutdown, cancellation, and blocking work.",[30,2495,2497],{"id":2496},"frequently-asked-questions","Frequently asked questions",[332,2499,2501],{"id":2500},"which-client-should-a-fastapi-or-asyncio-app-use","Which client should a FastAPI or asyncio app use?",[10,2503,2504],{},"Choose based on what the application's Kafka integration needs:",[35,2506,2507,2517],{},[38,2508,2509],{},[41,2510,2511,2514],{},[44,2512,2513],{},"Requirement",[44,2515,2516],{},"Better starting point",[54,2518,2519,2528,2538],{},[41,2520,2521,2524],{},[59,2522,2523],{},"Established asyncio lifecycle and async iteration",[59,2525,2526],{},[17,2527,27],{},[41,2529,2530,2533],{},[59,2531,2532],{},"First-party Schema Registry or one client for sync and async code",[59,2534,2535,2537],{},[17,2536,19],{}," AsyncIO",[41,2539,2540,2543],{},[59,2541,2542],{},"Per-message headers when producing",[59,2544,2545,2547,2548,2551],{},[17,2546,27],{},", or Confluent's synchronous ",[17,2549,2550],{},"produce()"," from a worker thread",[332,2553,2555],{"id":2554},"should-i-replace-kafka-python","Should I replace kafka-python?",[10,2557,2558,2559,2561],{},"No, not unless a concrete requirement is missing: Schema Registry serializers, a native librdkafka stack, commercial support, or an asyncio-native lifecycle. If you stay on ",[17,2560,23],{},", use the 3.x line. Configuration names can be mapped to another client, but delivery, commits, rebalancing, and shutdown still need to be verified.",[332,2563,2565],{"id":2564},"what-if-the-project-cannot-install-native-extensions","What if the project cannot install native extensions?",[10,2567,2568,2569,2571,2572,957,2574,2576],{},"Use ",[17,2570,23],{},". Its base package is a universal wheel and does not need a C compiler or a platform-specific Kafka library. Optional CRC and compression extras can still pull in native code, so skip those extras if the install must stay pure Python. ",[17,2573,19],{},[17,2575,27],{}," both ship native extensions.",[332,2578,2580],{"id":2579},"does-asyncio-make-a-kafka-client-faster","Does asyncio make a Kafka client faster?",[10,2582,2583,2584,2586],{},"No. Asyncio keeps the event loop free so the rest of the application can run while waiting on Kafka I\u002FO. It does not increase producer or consumer throughput by itself. For throughput-sensitive work, benchmark ",[17,2585,19],{}," with your message sizes, batching settings, and concurrency.",[332,2588,2590],{"id":2589},"can-different-python-clients-work-together","Can different Python clients work together?",[10,2592,2593],{},"Yes. A producer and a consumer do not need to use the same client. They must agree on topic names and key and value serialization, plus any header or Schema Registry conventions the application relies on. If different clients share a consumer group, verify that their rebalance protocols and assignment strategies are compatible.",[30,2595,2597],{"id":2596},"conclusion","Conclusion",[10,2599,2600,2601,2603,2604,2606,2607,2609],{},"For a new synchronous service, start with ",[17,2602,19],{},", then confirm that its native packaging fits your deployment. Choose ",[17,2605,23],{}," when pure-Python installation or PyPy support is the deciding requirement, or keep it when an existing application already runs reliably. Choose ",[17,2608,27],{}," when the application needs asyncio-native producer and consumer APIs.",[10,2611,2612,2613,2616],{},"Choose by technical fit first, then use repository activity and maintainer concentration to compare long-term maintenance risk. If you need windows, joins, or recoverable processing state, compare ",[139,2614,2615],{"href":141},"Kafka Streams in Python: Faust vs. Quix Streams"," instead.",[10,2618,2619],{},"This guide is maintained by the team behind Kafma.",[2621,2622,2623],"style",{},"html pre.shiki code .sifj9, html code.shiki .sifj9{--shiki-default:#8A8F98}html pre.shiki code .sUqoa, html code.shiki .sUqoa{--shiki-default:#E7E8EA}html pre.shiki code .sJl8Q, html code.shiki .sJl8Q{--shiki-default:#83CFAE}html pre.shiki code .sLaUg, html code.shiki .sLaUg{--shiki-default:#FFFFFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":986,"searchDepth":1011,"depth":1011,"links":2625},[2626,2627,2628,2633,2640,2644,2645,2652],{"id":32,"depth":1004,"text":33},{"id":148,"depth":1004,"text":149},{"id":165,"depth":1004,"text":166,"children":2629},[2630,2631,2632],{"id":19,"depth":1011,"text":19},{"id":23,"depth":1011,"text":23},{"id":27,"depth":1011,"text":27},{"id":483,"depth":1004,"text":484,"children":2634},[2635,2636,2637,2638,2639],{"id":490,"depth":1011,"text":491},{"id":548,"depth":1011,"text":549},{"id":670,"depth":1011,"text":671},{"id":818,"depth":1011,"text":819},{"id":897,"depth":1011,"text":898},{"id":920,"depth":1004,"text":921,"children":2641},[2642,2643],{"id":968,"depth":1011,"text":969},{"id":1732,"depth":1011,"text":1733},{"id":2460,"depth":1004,"text":2461},{"id":2496,"depth":1004,"text":2497,"children":2646},[2647,2648,2649,2650,2651],{"id":2500,"depth":1011,"text":2501},{"id":2554,"depth":1011,"text":2555},{"id":2564,"depth":1011,"text":2565},{"id":2579,"depth":1011,"text":2580},{"id":2589,"depth":1011,"text":2590},{"id":2596,"depth":1004,"text":2597},"2026-08-12","Compare confluent-kafka, kafka-python, and aiokafka — verified capabilities, GitHub metrics, and scenario recommendations.","md",{},null,"\u002Fblog\u002Fkafka-python-clients",false,{"title":5,"description":2654},{"loc":2658},"blog\u002Fkafka-python-clients",[2664,2665],"Kafka Client Libraries","Python","Fneum8L0oU9FZ_ZEdrb49aOLsmPjpWXVo0_M2IPdx6w",1786955621493]