Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
162866 stories
·
33 followers

GitHub’s model for secret detection: Finding more secrets with less noise

1 Share

OUR PIPELINE VS. THE PREVIOUS LLM PIPELINE

Smarter secret scanning, at a fraction of the cost

11.5%

higher acceptance

Owner-weighted alert precision

86%

lower median scan execution time

Post-push scanning

98%

lower serving cost

Compact model vs. remote LLM calls

Secret scanning works best when developers are confident in the findings. Catch too little, and real credentials can remain in a repository. Alert too often, and developers may spend time investigating strings that aren’t secrets.

Generic secrets make that balance especially difficult. The same string could be a real credential or a documentation placeholder, so detecting it requires understanding the surrounding code and text.

To address this challenge, we trained a secret classifier specifically for GitHub’s product needs: distinguishing real credentials from lookalikes while meeting the speed and efficiency requirements of scanning at scale.

In our companion post, Secret protection must scale with software, we explained why secret protection must keep pace with AI-accelerated development. Here, we go behind the scenes of the context-aware classifier powering that effort: how we designed, trained, and evaluated it to find more real secrets with less noise.

What we enabled

GitHub secret scanning operates at two key moments:

  • Push protection helps prevent secrets from entering a repository by scanning changes before a push is accepted, giving developers an opportunity to address the finding.
  • Post-push scanning works after code has been committed, continuously scanning repository content and creating alerts when potential secrets are detected so developers and security teams can investigate and remediate them.

We developed a fast classifier that reduced median post-push scan execution time by 86% compared with the previous LLM-based pipeline. That efficiency made it practical to extend generic secret detection to push protection, returning results before developers push changes, not only after code is committed.

Secret scanning blocks a commit with push protection after the model detects a secret on line 5 of the file.

Why secrets are hard to detect

Structured credentials often include a distinctive prefix, length, alphabet, or checksum. Generic secrets may not. Their syntax overlaps with build identifiers, checksums, asset hashes, sample values, and other non-sensitive strings. Context is the deciding signal.

Likely real credentialLikely harmless lookalike
A password assigned beside a production database URLThe same password-shaped value in a test fixture
A connection string in deployment configurationA localhost connection string in a setup guide
A high-entropy value bound to an API credentialA high-entropy checksum, build ID, or asset hash

These cases are hard negatives: strings that match a credential pattern but are not usable credentials. Adding more rules can suppress some of them, but each exception risks hiding a real secret. A learned classifier can instead use signals such as file path, secret type, variable names, and nearby code or text.

That is why we shipped a new scanner using a two-stage pipeline:

  1. Candidate generation: Regex filters scan content for potential secrets with high recall. This stage is optimized to catch broad families of credential-like patterns quickly and deterministically.
  2. Context-aware classification: A fine-tuned ModernBERT classifier evaluates each candidate and its surrounding context. It is trained to recognize the signals that separate real secrets from false positives, including placeholder values, examples, documentation snippets, generated content, and non-sensitive identifiers. Because the model is small and efficient to run on our inference infrastructure, it costs much less to serve and is simpler to scale than an LLM-based pipeline.

Impact:

  • 11.5% user acceptance improvement, reducing false positives.
  • 86% faster post-push secret detection execution time.
  • More than 98% cost savings compared with the LLM-based pipeline.

How our pipeline works

As content is scanned, regex patterns cast a wide net and flag anything that looks like a credential, so real secrets aren’t missed at the start. Each candidate then goes to a fine-tuned ModernBERT classifier, which reads the value together with its file path, variable names, and surrounding code. The classifier estimates how likely it is to be a real secret. High-confidence findings become alerts, and lookalikes such as placeholders, test fixtures, and checksums are filtered out before they reach developers.

HOW OUR PIPELINE WORKS

Broad first, careful second

STEP 1

Scan

Repository content, commits, pull requests, and other scanned surfaces.

STEP 2

Generate candidates

Regex patterns identify possible tokens, keys, and credential-like strings.

STEP 3

Classify

Fine-tuned ModernBERT evaluates candidate + context and assigns likelihood of a true secret.

STEP 4

Alert or suppress

High-confidence findings move forward; likely false positives are filtered.

The important design choice is that the model does not replace deterministic scanning. Instead, it complements it. Regexes remain the right tool for finding candidate strings quickly. The classifier is used where machine learning provides the most leverage: distinguishing “looks like a secret” from “is likely a real secret.”

The classifier model makes a best effort to distinguish “looks like a secret” from “is likely a real secret.”

A hard-negative problem: secrets that almost look real

Most false positives are not random. They are hard negatives: strings that match a credential pattern but are not usable credentials. Examples include documentation placeholders, toy examples in tests, redacted values, non-sensitive IDs, and generated fixtures. These cases are easy for a regex to match and hard for a purely rule-based system to suppress without accidentally losing real secrets.

ModernBERT helps because it can read the candidate together with nearby code and text providing contextual understanding comparable to an LLM without the latency and computational overhead of generating natural-language output. For example, a candidate surrounded by words like “example,” “dummy,” “fake,” or “replace-me” may be lower risk than a candidate assigned to an environment variable in a deployment file. The classifier learns these contextual differences from labeled examples rather than requiring engineers to encode every exception as another rule.

We chose ModernBERT because it provides a strong fit for this workload: it is compact, efficient, and well suited for classification over code-adjacent text. For secret scanning, the model needs to make a calibrated decision over short candidate windows with high throughput and low latency.

That makes a fine-tuned encoder classifier a better serving shape than a general-purpose LLM for this stage of the pipeline. The model can be trained directly on our decision boundary, and evaluated using the same recall and precision metrics that matter to secret scanning quality.

How we trained

The challenge was finding representative data for cases in which syntax alone is misleading. The training and evaluation strategy combines three sources: 

  • Product-derived examples from GitHub repositories, using feedback from the secret detection experience and additional human validation.
  • High-recall regex candidates from GitHub repository data, including human-annotated examples and weak labels used to expand coverage.
  • Synthetic examples targeted at sparse and difficult cases, such as documentation secrets, test fixtures, public keys, checksums, structured lookalikes, and near-miss pairs.

Synthetic rows pass deterministic validation and model-based quality review before inclusion. Training emphasizes real secrets, realistic false positives, and hard negatives that frequently confuse regex-only approaches. Each model input includes the candidate value, file path, secret type, and a bounded amount of surrounding context. We select thresholds through offline evaluation and then validate behavior on production-like traffic before broader rollout.

Before splitting the data, we grouped rows that share a repository, candidate value, or example so near-duplicates could not appear in both training and evaluation.

Training focused on the cases that matter most for alert quality: real secrets, realistic false positives, and hard negatives that regexes frequently match. The input representation includes the candidate secret string, file path, type and a bounded amount of surrounding context. The output is a classification score used by the scanner to decide whether the candidate should proceed.

We optimized for the product tradeoff: preserve or improve recall while reducing false positives and serving cost. In practice, that means the classifier threshold is selected using offline evaluation, then validated against production-like traffic before rollout.

The most important training principle was to make the model see the confusing examples. We included candidates that are syntactically similar to real secrets but semantically different, so the model learns not only what a secret looks like, but also what a false positive looks like in context.

The trained model is exported to ONNX format with 8-bit quantization, enabling fast inference.

Evaluation results

Online resultChange vs. previous LLM pipelineWhat it measures
Repository owner-weighted acceptance 11.5% higher Customer acceptance of detected findings 
Median post-push scan execution time 86% lower Production scan execution time 
Serving cost More than 98% lower Cost of the compact classifier compared with remote LLM calls 
Customer A/B evaluation results for our fine-tuned model compared to the previous LLM pipeline.

We evaluated the new pipeline’s impact in production in two stages: first against the production baseline on the same public traffic and then through a customer A/B experiment. 

  • Offline evaluation: On post-push scanning, the new pipeline achieved 13% higher precision and 19% higher recall than the previous LLM pipeline when evaluated on the same public traffic. 
  • Online evaluation: We then validated whether these quality improvements translated to customer outcomes through an A/B experiment against the previous LLM pipeline. Repository owner-weighted acceptance increased by 11.5%. We weight acceptance by repository owner to reduce the influence of customers who bulk-resolve large volumes of alerts at once, which can otherwise distort a simple average. 

Take this with you

The best security tool is the one developers trust enough to use. Higher precision means fewer distracting alerts. Higher recall means more real secrets are caught. Lower cost means we can keep improving coverage without making scanning prohibitively expensive.

For developers and security teams, this should translate into fewer false positives, and faster feedback in the places where secrets are most likely to be introduced: commits, pull requests, and everyday development workflows.

Hybrid systems are powerful. Regex gives us speed, transparency, and broad candidate coverage. ModernBERT gives us learned context understanding and false-positive reduction. The combination outperforms either approach used alone for this product constraint.

We also learned that model size is not the same as model usefulness. A smaller fine-tuned classifier can be the right answer when the task is narrow, the decision boundary is measurable, and serving efficiency is critical.

This is one step toward making secret scanning more accurate, scalable, and easy to use. Looking ahead, we are focused on two areas:

  • Building a continuous improvement flywheel. We will use production feedback loops to identify new false negatives and false positives, turning real-world signals into higher-quality training and evaluation data.
  • Exploring new model architectures. We are investigating approaches that can perform secret detection and extraction in a single step, reducing pipeline complexity while preserving accuracy and scale.

Acknowledgments

Huge thanks to the engineering, science and product teams across GitHub and Microsoft who helped build the training data, evaluation suite, serving stack, and rollout plan for this new secret scanner.

The post GitHub’s model for secret detection: Finding more secrets with less noise appeared first on The GitHub Blog.

Read the whole story
alvinashcraft
26 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Why Your Sandbox Never Quite Matches Production (And Why That's Fine)

1 Share
Sandbox testing works best when you stop chasing production parity. Learn what environment drift actually costs and which parts are worth fixing.
Read the whole story
alvinashcraft
28 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Apple unveils the new Apple TV 4K, supercharged by Siri AI

1 Share
Apple today announced the next generation of Apple TV 4K, delivering its most immersive home theater experience yet.

Read the whole story
alvinashcraft
28 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Why Early Releases Often Fail in Multi-Team Organizations

1 Share

At best, it means:

What’s the earliest reduced version we can put in front of real customers to validate against something we actually want to learn?

At worst, it’s just a date and an announcement with nothing clearly scoped behind it, so that gap needs to be closed before anyone starts building toward it.

That’s where things usually start to go wrong.

Business, product, and engineering often mean different things by “early release”

Once one customer flow is split across several teams, an early release becomes real coordination work.

Someone has to lead it end to end, and that usually falls to no one. The reduced scope drifts and nobody is coordinating the whole release. With each new team that holds a certain piece of the project, coordinating them gets harder. The fix is good management, and it requires someone to actually lead the release.

Part of the trouble is that the same words mean different things to different people who are, of course, the part of the same meeting. When the business asks for an early release, it usually means a reduced scope of something, made to be more of a barebones product than a full-sized one. This is something that’s enough to validate assumptions and deliver value while the rest is still being built. 

To most engineers, “done” means complete, so “early release” gets heard as “the whole thing, but fast.” Put an MVP, the smallest version that tests your least-sure assumption in the mix alongside full GA, the finished product for everyone, and one phrase is now pointing at three different targets.

Nobody draws the line between them, so scope drifts toward GA by default: a team builds one target while the plan assumed another, and that drift is what sinks these releases. 

How one customer journey becomes nobody’s problem 

Multi-team releases break along a predictable line, and it was mapped a long time ago. In 1968, Melvin Conway published a paper called How Do Committees Invent? with an observation that later became known as Conway’s Law. The law states that organizations that design systems are constrained to produce designs that copy their own communication structure.  

Applied to a release, it predicts the break before anyone writes code: split one customer journey across five teams that mostly talk within their own walls, and the software inherits the same boundaries the organization has. The release breaks at the boundary between two teams, where the calls that need the whole picture don’t belong to anyone.

Put that prediction next to a real feature. I kept it deliberately small here, just to picture the shape; the real ones are bigger and messier.  

A customer sends across dozens of destinations, each with its own registration rules. Provisioning sets the customer up to send, sender registration gets each sender approved per destination. The hard cases raise questions neither team can answer alone: when a sender is fine in one country and refused in the next, does provisioning collect a fallback, does registration substitute one, or does the campaign ship partial?  

No owners means no decisions

Since there’s no owner, there is no decision.

Instead, each team codes to its own assumption and passes its own tests, and the assumptions only collide in some cases that cross between teams. The first customer with a mixed set of destinations goes live approved in some and silently refused in others. This is a fix that looks obvious at this size, but at real scale it’s dozens of these calls across five teams, and the someone who should make them is still no one. 

It starts when the date is set before the scope or target customer is clear. Then teams start building without knowing where to stop. One team works on an edge case for full GA, while another builds for customers who aren’t onboarded yet.

“Early release” becomes “the whole thing” slowly, one decision at a time. It stays invisible because each team is doing good work on its own. The drift only exists at the level nobody is watching, which is the whole end-to-end journey, or the big picture. A release that goes out with no defined scope, no chosen customer, and no one leading it pushes the risk onto whoever is downstream.

Cutting scope on purpose is different. You choose what to leave out and handle the rest manually, so the customer still gets value without needing the unfinished parts.

The case against shared ownership

Shared ownership across those teams is where the whole falls through. Everybody owns a piece, which really means no one owns the whole.

When multiple teams each hold a piece of a customer journey, someone has to lead the end-to-end release. This should ideally be one or two people who know the flow in real detail: which service does what, where the boundaries between teams are, what a real customer actually experiences from first call to final result.  

A steering committee can set priorities and handle escalations, but it can’t lead the release day to day. A manager who only sees team status reports can’t do that either. The details that decide the release depend on how the pieces fit together, and neither of them is close enough to manage that.

In practice, that leadership is coordination work, not a box on the chart. The owner learns the whole flow and keeps it in their head. They draw the reduced-scope line and publish it, so every team is working from the same picture of what “first version” means.  

They watch for symptoms of a team drifting, which can include hardening a GA edge case or generalizing too early in the process. They decide where “reduced scope” ends and “next phase” begins and call the release. Most orgs already have someone near this role. Often, that’s a product manager or a TPM. 

Try making one person responsible for the release end to end

Define the reduced scope and target customer before you set the date. Write it down. Give it one owner who understands the whole flow. And when the first customer hits a gap, fix it in the shared path so the next customer doesn’t run into it too.

The reason it doesn’t happen is that leading five teams end to end is hard, unglamorous management work, and in most organizations it isn’t any single manager’s job. Each manager runs one team and looks after that team’s part of the release. The coordination across teams is no one’s job.

Some organizations avoid this because leading the whole is already built into someone’s job, or the structure is flat enough that the whole stays visible. The teams aren’t weak and nobody is being lazy; the job that needs doing simply isn’t anyone’s job. The fix is to make one person responsible for the release end to end, and to give them the room to actually lead it. 

Sometimes, though, one person genuinely can’t lead the whole thing, however skilled they are. In a matrix organization, an agency where the client signs off every step, or a regulated field where the approval path is set from outside, the flow crosses boundaries a single coordinator can’t reach across. 

If your structure genuinely prevents one person from leading end to end, no release process will fix it, because the real constraint is how the organization is wired. The release is only where that constraint first becomes visible. 

The post Why Early Releases Often Fail in Multi-Team Organizations appeared first on ShiftMag.

Read the whole story
alvinashcraft
31 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

When Architecture Decisions Actually Apply

1 Share

In my previous Radar article, “Architectural Guardrails for AI-Generated Code,” I argued that AI coding agents need a layer that can hold architectural decisions in a structured corpus, retrieve the relevant ones, put them into the agent’s context before it writes code, and enforce explicit constraints with reproducible checks. Testing that model exposed two distinctions I had compressed together.

  1. Retrieving a decision because it is relevant doesn’t mean the decision applies to the artifact being changed.
  2. A decision that does apply isn’t automatically suitable for deterministic enforcement.

The first distinction is between relevance and authority; the second is between guidance and enforcement.

Here’s the story of how one controlled repository made this distinction clear. The project used local JSON-backed persistence for its current phase, and an active architecture decision ruled out PostgreSQL, ORMs, and database migrations for the command-line application. The task asked the coding agent to change that application’s storage module, so the decision was not merely related to persistence in general; it had authority over the part of the repository being changed. The record was retrieved successfully and placed in the agent’s context before work began.

The agent still proposed PostgreSQL, together with an ORM and a migration path. Under my original four-capability model, that looked at first like a retrieval failure. It wasn’t. The decision was found and was current, and it arrived at the right moment. What was missing was an applicability signal that told the system that this decision governed the storage module being edited rather than serving as one more relevant document for the model to weigh against nearby code and other context.

Retrieval finds; applicability governs

Retrieval helps us determine which architectural decisions might be relevant to a task. That’s a search problem, and teams have increasingly capable ways to solve it: indexed repositories, connected documentation, exposed decision records and service catalogs, semantic search, and project memory. These techniques help an agent see useful material before it writes code. They don’t, by themselves, answer a different question: Which of those decisions has authority over the change in front of the agent?

Suppose a repository contains two persistence decisions. One requires PostgreSQL for an analytics service; the other requires local file storage for a command-line tool. If the agent is editing the command-line tool’s storage module, both decisions may rank highly for a query about persistence, but only the local-storage decision applies to that artifact. Determining which decision governs the change requires scope, lifecycle, precedence, and a clear record of which decisions replace earlier ones. I argued for precedence and lifecycle in the previous article; scope deserves equal attention because scope is what tells the system where a decision has authority.

A related problem is that architectural information is usually scattered across several kinds of documents. Humans know that an old design note, a README, an accepted architecture decision record, and a current platform standard don’t necessarily carry the same authority, even when all four discuss the same topic. Models don’t know that unless the system preserves the distinction. When those sources are flattened into one context window, the hierarchy among them can disappear. I think of this as authority flattening: Information remains available, but the signal about which information is binding becomes weaker. That’s useful when a design question is genuinely open; it’s risky when the team has already answered the question.

Research on architectural decision violations points to a similar boundary. A 2026 study by Su and colleagues examined 980 ADRs across 109 open source repositories. The models were strong when decisions were explicit and inferable from code but less accurate when compliance depended on deployment configuration or organizational knowledge. The study evaluated violations after code was written rather than guidance before generation, but the underlying limitation is similar: A model can retrieve the right document and still make the wrong architectural choice when applicability or authority remains implicit.

What scope changed

I tested this distinction in a small controlled experiment using seven coding tasks, repeated under two conditions with the same coding agent and model configuration. In one condition the agent worked without the relevant architectural guidance; in the other, architectural decisions were supplied before it began changing code. Independent reviewers assessed the first attempts for both architectural compliance and whether the requested work was actually completed. The guidance changed behavior: First-attempt compliance on the architecture-sensitive tasks improved from 6 of 15 runs to 10 of 15, while successful task completion was essentially unchanged.

The more interesting result was a failure inside the guided condition. In several authentication tasks, the agent received a storage-related architectural decision that was genuinely relevant to the surrounding problem and then implemented additional persistence work that the task had never asked for. Nothing was wrong with the decision, and retrieval had done its job. Relevance had simply been presented without enough information about authority. The experiment made two limits explicit: A decision can be relevant without governing the artifact being changed, and even a governing decision doesn’t authorize the agent to widen the task. Applicability tells the system where a decision may constrain work; it isn’t permission to invent more work.

Blocking is easier than guiding

The second distinction forced me to revise another part of the original model. The previous article emphasized deterministic enforcement: when a team has made an explicit decision and a violation can be identified from observable evidence, a blocking verdict should come from a reproducible rule rather than a model’s judgment. I still think that’s the right standard for blocking. The important qualification is that only a subset of architectural decisions can meet it without pretending that judgment has become deterministic.

“Do not introduce SQLAlchemy into this component” is comparatively easy to express as a rule, easy to check, and easy to block. “Use the existing persistence abstraction correctly” is different. Most of its meaning is architectural rather than syntactic: The right implementation depends on which abstraction is intended, how it’s used in this part of the system, and what surrounding constraints are already in force. The first statement describes a prohibition that can plausibly become a deterministic control. The second describes a sanctioned path and is better treated as guidance unless the team can make the relevant evidence and boundary precise.

Earlier experiments with pregeneration guidance pointed in the same direction. Adding more architecture-related context didn’t reliably improve behavior because what was missing was often not another prohibition; it was a clearer description of the accepted implementation path. A guardrail layer built entirely around blocking will become very good at saying no. Useful architectural governance has to do both jobs: block the known violations when the evidence is precise enough and carry positive architectural direction for the much larger set of decisions that still require interpretation.

When judgment becomes authority

This doesn’t reduce the role of models; it puts probabilistic reasoning where it’s useful. Models are good at interpretation: reading ambiguous guidance, surfacing decisions that might bear on a change, explaining the consequences of a boundary violation, and proposing how to bring a change back into line with the intended design. Deterministic logic is better suited to decisions the team has already settled and can state in terms that a check can reproduce. The mistake is asking either mechanism to do both jobs.

Once a system says that a proposed change violates an architectural rule, the standard changes. An engineer should be able to ask which decision applied, why it applied to this part of the codebase, what evidence triggered the result, and whether another developer running the same check would get the same answer. That doesn’t require every part of architecture to become formal policy. It requires a clear boundary around where uncertainty is allowed: Models may help find and explain architectural context, but a blocking decision shouldn’t ultimately reduce to “the model thought this looked wrong.”

Humans routinely work with architectural ambiguity. We weigh incomplete evidence, local context, and competing trade-offs, often using heuristics rather than formal rules. Models can help with that interpretive work too, but the result remains probabilistic. The problem begins when an ambiguous judgment is treated as a blocking rule. Deterministic enforcement requires a boundary precise enough that the same evidence produces the same verdict.

The distinction matters even more when a team uses several coding tools at once. One developer may use Claude Code, another Codex, another Cursor, while automated agents perform background maintenance. The models and retrieval mechanisms can differ, but the team’s architecture shouldn’t change with the tool. A shared set of decisions can sit underneath those environments as the source of authority, while each tool consumes guidance in its own way and the enforceable subset is checked consistently.

What I would add to the original model

I would now amend the original four-capability model in two places.

Retrieval should surface candidate decisions, while applicability determines which of those decisions actually govern the current artifact or action, using scope together with lifecycle and precedence. Then guidance and enforcement should remain separate outcomes: Some applicable decisions are precise enough to support deterministic controls, while others should influence the implementation without becoming binary rules.

That separation leaves the agent free to reason where the architecture is genuinely open while preserving authority where the team has already made a decision. It also avoids a common overcorrection. Once teams see that some architecture can be enforced automatically, the temptation is to formalize everything. A great deal of architecture is still judgment. “Keep domain boundaries narrow” or “prefer asynchronous integration when immediate consistency is unnecessary” can be valuable guidance without being safe material for an automatic block. The level of authority a system exercises should follow the precision of the decision and the evidence available to evaluate it.

For years architectural governance ran largely on human process: Someone wrote the decision record, an architect reviewed the important changes, experienced engineers carried part of the history in their heads, and code review caught some of what slipped through. AI coding agents change the economics of that process because implementation can now move faster than architectural intent can be reexplained and rereviewed by hand. Giving agents more context is necessary, but it’s not sufficient. The harder job is preserving the difference between information that may be useful, a decision that actually applies, guidance that should shape an implementation, and a constraint that is precise enough to stop one.

The goal isn’t to constrain every choice an agent makes. It’s to stop decisions the team has already made from quietly turning back into suggestions. That requires more than retrieving the right document. The system has to know whether the decision is current, where it has authority, and what kind of authority the team intended it to have.



Read the whole story
alvinashcraft
32 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Python vs Go: A Practical Comparison for Developers

1 Share

Two things are true about Python: It’s the most popular programming language in the world, and it’s the most common companion language for Go developers. How do we know that? From the Developer Ecosystem 2026 survey by JetBrains.

But we also know a lot more about the developers who use these two languages – both from quantitative data from different surveys, as well as qualitative data from our interviews with professionals who switched from Python to Go.

In this article, we share findings from these sources, going well beyond the simple syntax comparisons you will usually find. We will look at how the two languages differ, what the surveys tell us about the people who use them, and what our interviews say about the trade-offs between Python and Go, so that if you’re considering making the leap, you don’t have to dive in blind.

TL;DR

  • The article compares Python and Go across language design, performance, tooling, developer profiles, and migration experiences.
  • Python favors expressive code and rapid iteration; Go favors explicit, standardized code that is easy to maintain across teams.
  • Go excels in raw performance and concurrency, and is widely used in cloud infrastructure. Python remains stronger for machine learning, data science, and scientific computing.
  • Go developers are typically more infrastructure-focused and more senior. Go is rarely someone’s first language, whereas Python is very beginner-friendly.
  • Python leads in building AI models, yet Go developers create AI integrations at nearly the same rate: 46% vs 44%.
  • Moving to Go rarely means abandoning Python. Most teams use both, with Go for services and infrastructure and Python for AI and data workloads.

A note about the data

Unless stated otherwise, all survey figures come from the JetBrains Developer Ecosystem Survey 2026 (28,945 responses, fielded May–July 2026). We compare two groups: developers who selected Go among their primary languages (1,836) and developers who selected Python (11,298). The groups overlap, with 619 respondents selecting both languages. Therefore, every gap below is a conservative estimate of the real difference. Some questions were shown to only a part of each group, so bases are provided for reference. The qualitative material comes from interviews with developers who moved production workloads from Python to Go. We conducted the interviews between April and May 2026 and included seven participants who began using Go within the past year.

Python vs Go – languages compared

Core philosophy

On paper, Python and Go sound like they’d get along. Python lays out the core principles in the Zen of Python: Simple is better than complex, readability counts, there should be one obvious way to do it, etc. Go, as per Effective Go, “focuses on simplicity, reliability, and efficiency”, and is “specifically designed to make it easy to build software at scale”.

In practice, Python often optimizes for the person writing the code, offering multiple ways to say the same thing. Go optimizes for the person (or, nowadays, possibly the agent) reading someone else’s code two years later, so it picks one way to say most things and makes you spell it out. The goal is for all Go code to look like other Go code.

We point this out right at the beginning, because however similar these two philosophies look, this difference in approach underlies almost all the other language design differences that follow.

Ease of use and learning curve

Python is arguably one of the easiest programming languages to learn among those widely used in production. The syntax resembles natural language, the core set of constructs is small, and beginners can focus on programming ideas instead of language mechanics, leading to less frustration and faster results. Surveys consistently show Python to be one of the most popular programming languages (if not the most popular). In 2026, 10% of Python developers have been coding for less than a year, 23% are students or working students, and 19% hold junior positions, showing the language has a strong early-stage user base.

Python’s popularity among early learners is almost self-perpetuating. Initially, the language was well-suited to introductory courses and learning materials largely because it lets beginners print “Hello, world” with little ceremony, bypassing much boring theory in favor of real outputs. It also has the added benefit of being a generalist language that can handle a variety of use cases. Later, the sheer number of introductory courses and learning materials made it a natural choice for anyone who wanted to pick up programming but didn’t know where to start.

It’s not the same case with Go. In fact, you would be hard-pressed to find courses that teach you programming through Go. There are two reasons for that. First, Go 1.0 was released in 2012, long after Python had already become firmly embedded in CS curricula. The other is that Go solves problems that beginners don’t have. Explicit error handling, static types, and interfaces, which we’ll discuss later, all pay off across a large codebase maintained by a team over years. Go also has a much narrower set of implementations than Python, which makes it even less appealing for beginners.

That said, Go was also designed to be easy to learn, but for a different reason: Any large team should be able to onboard a new engineer quickly. Many Go developers will say that if you already know general programming concepts, you can become productive in Go in a matter of days or weeks. Developers we talked to said that Go “feels as easy to write as Python” and that it “strikes a good balance between Python’s simplicity and Java’s explicit nature”.

Syntax and readability

When you read Python, you can often follow it even without programming experience, because it reads relatively close to English. Python is dynamically typed, so type declarations are optional, though in practice, many companies and large codebases now write Python with type hints throughout, checked by tools like mypy or Pyright. Most of the ecosystem follows the formatting conventions set out in PEP 8, but they are still optional, and so some teams diverge from them.

Go, by contrast, is explicit and deliberately limited, which contributes to the cross-team readability we mentioned. It is statically typed, which makes it noticeably more verbose than Python. That was the main syntactic complaint raised by the developers we interviewed. Formatting in Go is not a matter of preference: gofmt will shape your code into the canonical form, whether you like the conventions or not.

One syntactic difference that developers consistently pointed out as a big adjustment when moving from Python to Go was error handling. Python lets you push failure handling to the edges of a function with try / except. Experienced Go developers clutch their pearls at the sight of that.

# Python: handle failure where it is convenient
try:
    profile = get_user(user_id)
except UserNotFound:
    return render_404()
// Go: handle failure where it happens
profile, err := getUser(userID)
if err != nil {
    if errors.Is(err, ErrUserNotFound) {
        return render404(w)
    }
    return fmt.Errorf("get user %s: %w", userID, err)
}

The Go version is longer, and in a large handler, developers will find themselves writing the if err != nil boilerplate ad nauseam. In return, they get control flow with no invisible jumps: Every path a value can take is explicit. Both approaches come with trade-offs.

Type system

Python’s dynamic typing checks types at runtime. This gives developers flexibility in writing and can speed up iteration, but it also means some type errors only show up when the code runs. The flexibility extends to the object model, which relies on duck typing: The code cares less about what an object is than what it can do. The developers we interviewed said they sorely missed duck typing, as it makes testing and mocking more difficult in Go.

Go checks types before the program runs. This results in fewer type-related failures reaching production and makes refactoring safer, but also causes code verbosity, as we touched on earlier.

Object model and polymorphism

Python is object-oriented in the way that most developers first learn the term. Everything is an object, and classes inherit from other classes (several at once, if you insist). Polymorphism works in two ways: down the class hierarchy when a subclass overrides its parent’s method, and sideways through duck typing, where anything with a read() method can be handed to code that expects a file.

Go has none of that hierarchy. There are no classes, no inheritance, and no way to declare that one type is a subtype of another. Instead, structs have methods attached to them, as well as interfaces that types satisfy implicitly without ever naming them.

# Python: the implementation announces its role
class Store(ABC):
    @abstractmethod
    def get(self, key: str) -> bytes: ...

class RedisStore(Store):
    def get(self, key: str) -> bytes:
        ...
// Go: the consumer declares what it needs; RedisStore never mentions Getter
type Getter interface {
    Get(key string) ([]byte, error)
}

func handleRead(g Getter, key string) ([]byte, error) {
    return g.Get(key)
}

Notice how the dependency runs. In Python, RedisStore inherits from Store, so the abstraction sits with the implementation. In Go, handleRead declares the one method it actually calls, and RedisStore never learns that Getter exists. That’s why Go developers say to “accept interfaces, return structs”, and that’s why interfaces stay small – io.Reader and io.Writer have a single method each.

Performance and speed

Go follows a traditional compilation model, producing a native binary. Python, on the other hand, takes a hybrid approach: Source code is compiled to bytecode, which the interpreter then executes.

As most compiled languages do, Go wins in terms of raw speed. You can compare the patterns across latency, throughput, and startup time on The Computer Language Benchmarks Game. Microbenchmarks like these don’t really translate directly to real workloads, and we wouldn’t be surprised if you made nothing of them. Our interviewees told us what the difference meant in production for them: One team migrated to Go after cold starts on AWS Lambda in Python exceeded 10 seconds; another measured a tenfold improvement in request times after rewriting their Python service in Go.

But raw language speed matters only when your service is actually compute-bound or latency-sensitive, and plenty of services are neither. Equally importantly, the Python interpreter is not slow where it counts most for one of its largest user bases. In machine learning, data work, and numerical computing, libraries like NumPy and PyTorch offload expensive operations to optimized native code, making interpreter overhead much less relevant. When we asked migrating developers where they decided to keep Python code, they confidently listed all AI and ML workflows – LLMs, chatbots, RAGs, and model training.

Memory management

Memory management is another important part of the performance discussion. Both languages manage memory for you, but differently: Go uses a tracing garbage collector, while CPython uses reference counting alongside a cyclic garbage collector. This affects what developers can fine-tune and what they need to design around.

Go’s GC runs concurrently with the program and is designed to minimize stop-the-world pauses. Developers can tune this behavior: GOGC and GOMEMLIMIT set the pacing, and the memory profile (heap and allocs) tells you when a service allocates too hard.

In CPython, an object is typically freed the moment its last reference disappears. Memory use is predictable, and pauses are rarely worth measuring, but the cost is spread across every operation, and there’s little to room tune it.   

Concurrency and parallelism

Even though both languages support concurrency, developers we talked to cited better concurrency as the reason why they switched from Python to Go.

Goroutines are central to Go’s design. They are lightweight threads managed by the runtime. They are cheap to create, carry little overhead, and scale to thousands of concurrent operations. The runtime handles the scheduling, which makes the model simpler than in Python – there is no separate async/await syntax, so a function is just a function. However, if you start to spawn goroutines without controlling their lifecycle, you’d better be ready to deal with race conditions, leaks, and deadlocks before long.

The other half of the concurrency model in Go are channels – typed conduits that pass values between goroutines and synchronize them. Instead of guarding shared state with a lock, Go can pass the value to whichever needs it next. A select statement waits on several channels at once, which is how Go expresses timeouts, cancellation, and fan-in using built-in language constructs. These very same primitives also produce common Go bugs: goroutine leaks and more deadlocks. 

Meanwhile, Python relies on standard libraries, single-threaded event loops, and sub-processes to work around interpreter constraints. It offers threading, but in CPython, the global interpreter lock (GIL) has historically prevented threads from running Python bytecode simultaneously, making it ineffective for CPU-bound parallelism. For I/O-bound concurrency, there is asyncio, and for real parallelism there is multiprocessing, but that adds memory overhead and requires inter-process communication.

It’s worth noting that the GIL itself is no longer a necessity – starting with Python 3.13, PEP 703 introduced an officially supported free-threaded build, and 3.14 continues that work. Most production code still runs with the GIL in place, but with each new release, the claim that “Python can’t do real threading” is becoming less true.

# Python: async/await, and the coloring that comes with it
async def fetch_all(urls):
    return await asyncio.gather(*(fetch(u) for u in urls))
// Go: ordinary functions run concurrently
var wg sync.WaitGroup
for _, u := range urls {
    wg.Add(1)
    go func() {
        defer wg.Done()
        fetch(u)
    }()
}
wg.Wait()

The approach to concurrency gives Go much of its practical advantage in high-throughput services, and having experienced both, our interviewees praised Go for being “async by default” and better suited for high-concurrency components, and they described it as having a superior concurrency model that’s highly performant and appealing for real-world use cases.

Libraries, frameworks, and IDEs

Go’s self-contained ecosystem

Go was never built as just a programming language, but as an ecosystem. As the Go team puts it, the goal was “an end-to-end platform with tooling all around the software development lifecycle” (Google for Developers), with formatters, test frameworks, dependency management, and security tools included in the toolchain, alongside a standard library that’s comprehensive enough to make external frameworks optional, if not irrelevant.

The Developer Ecosystem 2026 survey shows how successful the Go team has been in achieving that goal. For example, among Gophers, the standard html/template and text/template library packages are used by 31% and 22% of developers respectively, whereas the only other significant alternative – templ – is used by 11%.

Almost half of Gophers either don’t write unit tests or don’t use testing frameworks: 14% don’t write unit tests at all, and 35% don’t use frameworks for testing – the testing package provides everything they need in that regard. Others may also reach for tools such as Testify (31%) or GoMock (25%). The remaining libraries are far less popular.

For web development, 46% of developers use the standard net/http library, compared to 48% who use Gin. This proves that where a third-party framework exists, it doesn’t compete with the many other frameworks, but only with the standard library. Oftentimes, it loses.

Go developers

Libraries and frameworks Go developers use

Template engines used for Go development

Which template engines do you use for Go development, if any?

None52%
html/template31%
text/template22%
templ11%
gomponents5%
pongo24%
Plush1%
Other2%

Source: JetBrains Developer Ecosystem Survey 2026, weighted data. Base: Respondents who answered the Go section (n = 1,529). Multiple answers allowed.

Testing frameworks and mock libraries in Go

Which testing frameworks or mock libraries do you regularly use, if any?

I write unit tests but don’t use any frameworks35%
Testify31%
GoMock25%
I don’t write unit tests for Go14%
Ginkgo7%
go-sqlmock6%
Godog5%
Gomega3%
GoConvey1%
Other2%

Source: JetBrains Developer Ecosystem Survey 2026, weighted data. Base: Respondents who answered the Go section (n = 1,518). Multiple answers allowed.

Go web frameworks in regular use

Which Go web frameworks do you regularly use, if any?

Gin48%
net/http46%
gorilla/mux15%
go-chi/chi15%
Echo13%
Fiber13%
None12%
Beego5%
Buffalo2%
Revel1%
Other5%

Source: JetBrains Developer Ecosystem Survey 2026, weighted data. Base: Respondents who answered the Go section (n = 1,519). Multiple answers allowed.

Python’s broad ecosystem

Python’s ecosystem works the other way around. The Python Package Index (PyPI) is vast and mature, and where the standard library stops, several strong alternatives tend to compete.

Take web frameworks, for example. Half of Python developers use FastAPI, and Django (31%) competes closely with Flask (30%). The data science landscape is more fragmented, and developers use those libraries simultaneously: 69% use NumPy, 68% use pandas, 50% use PyTorch, 49% use Matplotlib, etc. With Python, there’s often no clear leader, and choosing the right framework or library is part of the job.

Python developers

Frameworks and packages Python developers use

Web frameworks used with Python

What web frameworks / libraries do you use in addition to Python?

FastAPI50%
Django31%
Flask30%
None28%
Other3%

Source: JetBrains Developer Ecosystem Survey 2026, weighted data. Base: Respondents who answered the Python section (n = 4,276). Multiple answers allowed.

Data science packages used with Python

What data science packages do you use in Python?

NumPy69%
pandas68%
PyTorch49%
Matplotlib48%
scikit-learn35%
OpenCV32%
TensorFlow30%
SciPy29%
Seaborn20%
Keras15%
None14%
XGBoost13%
Polars8%
Other1%

Source: JetBrains Developer Ecosystem Survey 2026, weighted data. Base: Respondents who answered the Python section (n = 4,277). Multiple answers allowed.

IDEs & editors

When it comes to editors, we see a similar pattern unfold. Go has an excellent language server, which makes general-purpose editors a viable alternative to a Go-specific IDE. When asked which IDEs or editors they use for Go development, 49% reported using GoLand, while 48% reported using VS Code. 

Go developers

IDEs and editors used for Go development

Which IDEs or editors do you use for Go development?

GoLand49%
Visual Studio Code48%
Zed14%
Cursor14%
Neovim10%
IntelliJ IDEA8%
Vim4%
Visual Studio4%
Sublime Text2%
Emacs1%
Windsurf1%
Atom<1%
Other4%

Source: JetBrains Developer Ecosystem Survey 2026, weighted data. Base: Respondents who answered the Go section (n = 1,529). Multiple answers allowed.

One reason is how much of Go’s surrounding ecosystem developers can access without having to assemble it themselves. GoLand installs with a test runner, debugger, coverage, and profilers wired into the toolchain. The analysis runs across the whole project, rather than only the open file. Interprocedural nil checks and unhandled-error inspections can catch the mistakes a Python developer might otherwise only see at runtime. Suffice it to say, Alan Donovan of the Go team has also described traditional IDEs like ours as setting “the gold standard” for refactoring because of their tight integration between the analysis logic and the user interface.

Python developers

Main IDE or editor for Python development

Which IDE or editor do you use the most for Python development?

Visual Studio Code41%
PyCharm22%
Cursor10%
PyCharm Pro8%
Jupyter Notebook5%
Vim / Neovim3%
IntelliJ IDEA3%
Zed2%
Notepad++2%
IDLE1%
Datalore<1%
Windsurf<1%
Emacs<1%
Other2%

Source: JetBrains Developer Ecosystem Survey 2026, weighted data. Base: Respondents who answered the Python section (n = 4,276). One answer per respondent.

The Python side is more fragmented and has more Python-specific options, such as Jupyter Notebook and, of course, PyCharm. The latter is used by 30% of Python developers (PyCharm – 22%, PyCharm Pro – 8%), with VS Code at 41%. Notebooks explain much of the fragmentation, since data and service work don’t necessarily require the same toolset. Whatever you build in Python, PyCharm has first-class support for your stack, your frameworks, and your workflow – for web, data, and ML workflows – with notebooks running alongside a debugger and type checker. It parses your code and resolves usages, types, and dependencies throughout your entire project. So you always know exactly what your code does and what will break if it changes, for you and your agents alike.

If you use both Go and Python – as a quarter of Gophers do – it’s worth noting that both GoLand and PyCharm are built on the same platform, so keymaps, shortcuts, and settings sync between them. GoLand also supports Python functionalities through the Python Community Edition plugin.

Python vs Go – broader landscapes

The language itself is one thing, but many other factors go into deciding which language you choose to work with. Developers consider what the languages are used for, who uses them, and how they’re maintained. In this section, we’ll provide insights on the factors that shape the broader landscapes of Python and Go.

Go developers are more senior

Across all questions about age, experience, and seniority in the Developer Ecosystem 2026 survey, Gophers tend to be further along in their career than Python developers.

On overall professional coding experience (not just experience in their main programming language), 20% of Go devs report 16 years or more, compared to 12% among Python developers. At the other end, 9% of Gophers have 1–2 years of experience, compared to 20% of Python developers.

Most Go professionals have senior roles, at 60%, with only 2% being trainees and 10% juniors. Meanwhile, 42% of Python professionals are seniors; trainees (6%) and juniors (19%) make up a quarter of the cohort.

72% of Go developers are employed full-time, compared to 51% of Python developers. Students and working students make up 8% of Gophers, compared to 23% of the Python population.

Finally, by age, the largest group of Go developers is aged 30–34 (23%), compared to Python’s largest group, aged 21–24 (22%).

These differences align with the point we made earlier: Python is a very popular first language for learners, while Go is almost never chosen as a first language and instead is picked up by more experienced developers later in their careers.

It’s important to keep this in mind as you read the following sections on developer demographics, because a lot of these numbers may look like differences between two languages, where in reality, they’re just differences between a senior population vs a general one that you would see regardless of what ecosystems you compare.

Go vs Python developers

Experience and seniority

Professional coding experience

How many years of professional coding experience do you have?

GoPython
Less than 1 year*Go 2%Python 10%
1–2 years*Go 9%Python 20%
3–5 yearsGo 22%Python 25%
6–10 years*Go 28%Python 19%
11–15 years*Go 17%Python 9%
16+ years*Go 20%Python 12%
No professional coding experience*Go 1%Python 5%

Source: JetBrains Developer Ecosystem Survey 2026, weighted data. Base: Go n = 1,836, Python n = 11,298. Go and Python developers are respondents who selected the language among their primary languages; those who selected both are counted in both groups. * Statistically significant difference (p < 0.05, adjusted).

Position level

What is the level of your current position?

GoPython
Trainee*Go 2%Python 6%
Junior*Go 10%Python 19%
Middle*Go 26%Python 30%
Senior*Go 60%Python 42%
OtherGo 2%Python 3%

Source: JetBrains Developer Ecosystem Survey 2026, weighted data. Base: Go n = 1,531, Python n = 6,891. Go and Python developers are respondents who selected the language among their primary languages; those who selected both are counted in both groups. * Statistically significant difference (p < 0.05, adjusted).

Employment status

Which of the following best describes your employment and involvement in software development?

GoPython
Employed full-time*Go 72%Python 51%
Employed part-time*Go 2%Python 3%
Self-employed or freelancer*Go 10%Python 11%
Founder or business ownerGo 4%Python 3%
Working student*Go 4%Python 9%
Student*Go 4%Python 14%
Not employed, with development experienceGo 3%Python 3%
Learning as a hobby or career transition*Go 1%Python 4%
Other*Go <1%Python 1%

Source: JetBrains Developer Ecosystem Survey 2026, weighted data. Base: Go n = 1,836, Python n = 11,298. Go and Python developers are respondents who selected the language among their primary languages; those who selected both are counted in both groups. * Statistically significant difference (p < 0.05, adjusted).

Age

What is your age range?

GoPython
18–20*Go 4%Python 9%
21–24*Go 13%Python 22%
25–29Go 22%Python 21%
30–34*Go 23%Python 16%
35–39*Go 17%Python 12%
40–49*Go 18%Python 14%
50–59*Go 4%Python 5%
60 or older*Go <1%Python 2%

Source: JetBrains Developer Ecosystem Survey 2026, weighted data. Base: Go n = 1,836, Python n = 11,298. Go and Python developers are respondents who selected the language among their primary languages; those who selected both are counted in both groups. * Statistically significant difference (p < 0.05, adjusted).

Salary follows seniority

Salary bands clearly show how experience affects other demographic data. Go developers are better represented in the top bracket: 9% report earning more than $180,000 a year, compared to 6% of Python programmers. Meanwhile, Python users cluster more in the lowest brackets.

Go vs Python developers

Annual salary, USD

Salary bands in USD, converted from local currencies.

GoPython
Up to 1,000*Go 0%Python <1%
Up to 1,800Go 1%Python 1%
Up to 6,000*Go 4%Python 8%
Up to 12,000*Go 6%Python 8%
Up to 18,000Go 6%Python 6%
Up to 24,000Go 5%Python 7%
Up to 36,000Go 12%Python 14%
Up to 48,000Go 11%Python 10%
Up to 60,000Go 9%Python 8%
Up to 84,000Go 13%Python 12%
Up to 120,000*Go 17%Python 12%
Up to 180,000Go 8%Python 8%
More than 180,000*Go 9%Python 6%

Source: JetBrains Developer Ecosystem Survey 2026, weighted data. Base: Go n = 1,115, Python n = 5,004. Go and Python developers are respondents who selected the language among their primary languages; those who selected both are counted in both groups. * Statistically significant difference (p < 0.05, adjusted).

However, if we look only at full-time developers, the differences are no longer statistically significant. The premium is attached to the seniority and employment status, not the primary language. In other words, learning Go itself will not guarantee you a higher salary, but the roles that require Go generally pay better.

What they build

The Developer Ecosystem survey also asks people what functionality their code implements.

Go developers more frequently reported:

  • 69% – providing APIs and services (Python – 41%)
  • 63% – integrating with APIs and services (Python – 47%)
  • 51% – application logic and workflows (Python – 37%)
  • 47% – user interface (Python – 41%)
  • 35% – libraries and frameworks (Python – 26%)

Meanwhile, Python developers reported higher rates for:

  • 38% – data processing and analytics (Go – 30%)
  • 36% – artificial intelligence and machine learning (Go – 20%)
  • 32% – data science and data analytics (Go – 15%)

The question of where their code is executed adds more context: A vast majority of Go developers target server, infrastructure, or cloud environments (74% compared to 57% of Python developers. On the other hand, 66% of Python developers target the desktop (Go – 47%).

Python is clearly a general-purpose language with a stronghold in AI, ML, and data work that favors local execution, while Go is heavily oriented towards networked services and infrastructure.

There is, however, a particularly interesting line item in the set: integration with AI. While AI development per se is a Python domain, integrations are not. 46% of Go developers report implementing AI integrations, against Python’s 44%, almost equal numbers. Asked about the types of development they do at work, 51% of Python developers reported working with AI and AI tools, compared to Go’s 48%. Go engineers may not train the models, but they are building AI-powered products at roughly the same rate as Python developers.

Go vs Python developers

What Go and Python developers build

What their code implements

Which specific functionality does your code implement?

GoPython
Integrating with APIs and services*Go 63%Python 47%
Providing APIs and services*Go 69%Python 41%
Integration with AIGo 46%Python 44%
User interface*Go 47%Python 41%
Application logic and workflows*Go 51%Python 37%
Data processing and analytics*Go 30%Python 38%
Libraries / frameworks*Go 35%Python 26%
Artificial intelligence and machine learning*Go 20%Python 36%
System tools and components*Go 27%Python 19%
Data science / data analytics*Go 15%Python 32%
Automating software testing and QA*Go 23%Python 20%
Ad hoc scripts*Go 18%Python 15%
Network communication protocols*Go 19%Python 12%
Security, encryption, and cryptographic protocols*Go 18%Python 13%
Audio or video processing*Go 8%Python 10%
Hardware interfacing and control systems*Go 8%Python 10%
Simulations and predictive modeling*Go 5%Python 9%
Rendering and processing graphics (2D/3D)*Go 5%Python 7%
Blockchain technologyGo 4%Python 3%
Other*Go <1%Python 1%

Source: JetBrains Developer Ecosystem Survey 2026, weighted data. Base: Go n = 1,836, Python n = 11,298. Go and Python developers are respondents who selected the language among their primary languages; those who selected both are counted in both groups. Multiple answers allowed. * Statistically significant difference (p < 0.05, adjusted).

Where their code runs

On which platforms is your code executed?

GoPython
Server / infrastructure / cloud*Go 74%Python 57%
Browser*Go 63%Python 57%
Desktop*Go 47%Python 66%
Mobile*Go 32%Python 26%
IoT / embeddedGo 11%Python 12%
WebAssembly*Go 7%Python 5%
Game consoles*Go <1%Python 2%
Other*Go <1%Python 1%

Source: JetBrains Developer Ecosystem Survey 2026, weighted data. Base: Go n = 1,836, Python n = 11,298. Go and Python developers are respondents who selected the language among their primary languages; those who selected both are counted in both groups. Multiple answers allowed. * Statistically significant difference (p < 0.05, adjusted).

Types of development at work

Which types of development are you involved in at work?

GoPython
Backend*Go 77%Python 54%
Full-stack*Go 55%Python 44%
AI and AI toolsGo 48%Python 51%
Infrastructure / DevOps*Go 45%Python 31%
Frontend*Go 39%Python 35%
Automated testGo 22%Python 20%
Data science and ML*Go 11%Python 27%
DesktopGo 18%Python 19%
MobileGo 18%Python 16%
Embedded and IoTGo 7%Python 9%
GamesGo 5%Python 4%
I don’t develop software professionally*Go 1%Python 6%
OtherGo 1%Python 1%

Source: JetBrains Developer Ecosystem Survey 2026, weighted data. Base: Go n = 1,595, Python n = 7,427. Go and Python developers are respondents who selected the language among their primary languages; those who selected both are counted in both groups. Multiple answers allowed. * Statistically significant difference (p < 0.05, adjusted).

DevOps: Same job, different toolbox

One other point of convergence between Python and Go developers that deserves its own section is DevOps. Both groups are involved in that area, though Python developers (31%) somewhat less than Gophers (45%). The two groups also tend to use different tools.

  • For orchestration, Go developers are more likely to use tooling overall, and especially Kubernetes. Only 8% of Go developers don’t use container orchestration tools (compared to 17% for Python); 58% use Kubernetes (compared to 39%). The engineers we talked to cited Go’s deep integration with Kubernetes as one of the reasons they migrate entire services from Python to Go.
  • For configuration management, Terraform leads both groups. However, Python developers lean more toward cloud-native IaC tools (29% for Python, 23% for Go) or use nothing (21% for Python, 15% for Go), while Go developers choose GitOps more often (27% for Go, 21% for Python).
  • When it comes to DevOps practices, Go developers report using them more often overall, with one exception: AI-driven operations (12% of Go developers and 18% of Python developers). Python developers are also more likely to use no DevOps practices at all (6% for Python, 2% for Go).

So even if you move from Python to Go in the same type of role, the toolset change might be as big an adjustment as the language change itself.

Go vs Python developers

DevOps tools and practices

Container orchestration tools

Which container orchestration tools or services do you use?

GoPython
Docker ComposeGo 68%Python 65%
Kubernetes (incl. EKS, GKE, or AKS)*Go 58%Python 39%
Amazon ECSGo 14%Python 13%
I don’t use any such tools or services*Go 8%Python 17%
Docker SwarmGo 8%Python 7%
OpenShift*Go 2%Python 4%
HashiCorp NomadGo 2%Python 1%
Apache Mesos*Go <1%Python 2%
OtherGo 1%Python 1%

Source: JetBrains Developer Ecosystem Survey 2026, weighted data. Base: Go n = 1,435, Python n = 7,242. Go and Python developers are respondents who selected the language among their primary languages; those who selected both are counted in both groups. Multiple answers allowed. * Statistically significant difference (p < 0.05, adjusted).

Configuration management and IaC tools

Which configuration management or IaC tools do you use?

GoPython
Terraform*Go 47%Python 37%
Cloud-native IaC tools (CloudFormation/CDK, ARM/Bicep, etc.)*Go 23%Python 29%
GitOps*Go 27%Python 21%
Custom scripts or in-house solutionsGo 22%Python 22%
AnsibleGo 21%Python 22%
I don’t use any such tools*Go 15%Python 21%
Puppet, Chef, SaltStack, or similarGo 4%Python 5%
PulumiGo 3%Python 3%
OtherGo 2%Python 2%

Source: JetBrains Developer Ecosystem Survey 2026, weighted data. Base: Go n = 930, Python n = 3,109. Go and Python developers are respondents who selected the language among their primary languages; those who selected both are counted in both groups. Multiple answers allowed. * Statistically significant difference (p < 0.05, adjusted).

DevOps practices in use

Which of the following DevOps practices do you or your team currently use?

GoPython
CI/CD pipelines*Go 88%Python 83%
Containerization and orchestration*Go 61%Python 52%
Infrastructure as code (IaC)*Go 50%Python 42%
GitOps*Go 36%Python 26%
Platform engineering*Go 25%Python 18%
DevSecOpsGo 20%Python 20%
AI-driven operations*Go 12%Python 18%
Serverless (FaaS), multi-cloud, or hybrid cloudGo 17%Python 13%
We don’t use any DevOps practices*Go 2%Python 7%
OtherGo <1%Python 1%

Source: JetBrains Developer Ecosystem Survey 2026, weighted data. Base: Go n = 930, Python n = 3,110. Go and Python developers are respondents who selected the language among their primary languages; those who selected both are counted in both groups. Multiple answers allowed. * Statistically significant difference (p < 0.05, adjusted).

Operating systems

A curious difference surfaced when we asked developers about the operating system they use for their development environment. Go developers work on macOS (70%) and Linux (57%) significantly more than on Windows (44%). Meanwhile, Python developers use Windows first (66%), then split almost evenly between macOS (54%) and Linux (52%).

For developers planning to migrate to Go, sticking with Windows doesn’t have to complicate deployment, even when the target is a Linux server. For pure Go, building a Linux binary from any of the three operating systems takes no more than two environment variables, while a Python deployment still has to find a matching interpreter and native packages, wherever it ends up.

Go vs Python developers

Operating systems for development environments

On which operating systems are your development environments?

GoPython
macOS*Go 70%Python 54%
Windows*Go 44%Python 66%
Linux*Go 57%Python 52%
OtherGo <1%Python 1%

Source: JetBrains Developer Ecosystem Survey 2026, weighted data. Base: Go n = 1,836, Python n = 11,298. Go and Python developers are respondents who selected the language among their primary languages; those who selected both are counted in both groups. Multiple answers allowed. * Statistically significant difference (p < 0.05, adjusted).

Two different approaches to AI

We’ve already discussed using Python and Go for AI development, but what about using AI for Go and Python development? Both groups use AI heavily at work, but there’s a difference in how and what they use it for.

Go developers report using AI daily for tasks such as editing code across multiple files (60% vs 52%), agentic development of features or programs (51% vs 41%),  generating commit messages (51% vs 36%) and tests (47% vs 34%), or performing code reviews (39% vs 34%).

Meanwhile, Python developers lead on one task: learning new things about coding and software development (38% of Python developers vs 31% of Go developers), which is consistent with earlier data showing a larger early-career population among Python developers.

There is, however, a long list of tasks where the two groups are indistinguishable: refactoring, debugging, checking code for potential issues, asking general questions, or generating boilerplate – even though you’d expect Go developers to jump on the last one much more, considering the verbosity of the language.

Go vs Python developers

Tasks they use AI tools for every day

How often do you use AI tools for each of the following tasks at work? Share answering “Every day”.

GoPython
Generating code*Go 69%Python 64%
Editing code across multiple files*Go 60%Python 52%
Code completion*Go 55%Python 51%
Agentic development of features or programs*Go 51%Python 41%
Generating boilerplate, repetitive codeGo 45%Python 46%
Asking questions about software developmentGo 45%Python 45%
Generating code comments or documentation*Go 48%Python 42%
Generating commit messages*Go 51%Python 36%
Explaining bugs and offering fixesGo 40%Python 45%
Generating tests*Go 47%Python 34%
Improving or optimizing codeGo 40%Python 40%
Checking code for potential issuesGo 39%Python 41%
Performing code reviews*Go 39%Python 34%
Explaining codeGo 37%Python 36%
Brainstorming new ideasGo 35%Python 38%
Learning new things about coding*Go 31%Python 38%
Summarizing recent code changesGo 34%Python 34%
Debugging codeGo 32%Python 35%
Generating user documentationGo 32%Python 28%
Natural-language search for code fragmentsGo 31%Python 27%
Generating internal documentationGo 28%Python 24%
Refactoring codeGo 22%Python 22%
Converting code to other languagesGo 11%Python 13%

Source: JetBrains Developer Ecosystem Survey 2026, weighted data. Base: Respondents who rated these tasks (Go n = 993, Python n = 5,056); bases vary slightly by task. Go and Python developers are respondents who selected the language among their primary languages; those who selected both are counted in both groups. * Statistically significant difference (p < 0.05, adjusted).

So AI-assisted coding is common in both ecosystems. Go developers have simply wired it into the production chores of a maintenance-heavy codebase: commits, tests, reviews, and multi-file edits.

The groups also tend to use different tools. Go developers are more likely to use terminal and agentic tools like Claude Code (45% vs 40%), OpenAI Codex (24% vs 17%), Cursor (17% vs 12%), and OpenCode (12% vs 6%). Python developers, in turn, reach more for general-purpose assistants and Google or Microsoft surfaces like ChatGPT (20% vs 16%), Google Antigravity (9% vs 5%), and Microsoft 365 Copilot (4% vs 1%).

Go vs Python developers

AI tools used for coding at work

Which of these AI tools do you use for your coding and other development-related tasks at work?

GoPython
Claude Code*Go 45%Python 40%
OpenAI Codex*Go 24%Python 17%
GitHub CopilotGo 18%Python 19%
ChatGPT (web, desktop, or mobile app)*Go 16%Python 20%
Claude (web, desktop, or mobile app)Go 16%Python 17%
Cursor*Go 17%Python 12%
OpenCode*Go 12%Python 6%
Google Antigravity*Go 5%Python 9%
Google Gemini (web or mobile app)Go 6%Python 7%
JetBrains AI Assistant*Go 7%Python 5%
DeepSeek (apps or self-hosted)Go 5%Python 4%
CodeGPT plugin in VS CodeGo 5%Python 3%
Zed*Go 5%Python 2%
Gemini CLI*Go 2%Python 4%
JetBrains Junie*Go 4%Python 2%
Microsoft 365 Copilot*Go 1%Python 4%
TraeGo 2%Python 2%
Gemini Code AssistGo 1%Python 2%
CodeRabbit*Go 2%Python 1%
Google AI Studio*Go <1%Python 2%
PerplexityGo 1%Python 2%
TONGYI LingmaGo 2%Python 1%
WindsurfGo 1%Python 1%
Qwen CodeGo 1%Python 2%
Amazon Q DeveloperGo 1%Python 1%
OpenClaw*Go 1%Python 1%
JetBrains AirGo 1%Python <1%
DevinGo 1%Python 1%
Gemini in Android Studio*Go <1%Python 1%
Warp / OzGo <1%Python 1%
Cline*Go <1%Python 1%
NoneGo <1%Python 1%
ConductorGo 1%Python <1%
AmpGo <1%Python <1%
FactoryGo <1%Python <1%
BLACKBOX AI*Go <1%Python <1%
Google JulesGo <1%Python <1%
GitHub Agent HQGo <1%Python <1%
TabnineGo <1%Python <1%
GitLab Duo Agent PlatformGo <1%Python <1%
SupersetGo <1%Python <1%
GraphiteGo <1%Python <1%
Ona (previously Gitpod)Go 0%Python <1%
OtherGo 2%Python 1%

Source: JetBrains Developer Ecosystem Survey 2026, weighted data. Base: Go n = 1,482, Python n = 6,747. Go and Python developers are respondents who selected the language among their primary languages; those who selected both are counted in both groups. Multiple answers allowed. * Statistically significant difference (p < 0.05, adjusted).

One number that has to change

Software development remains a heavily male-dominated field, and the gap is particularly pronounced in Go, which – as it’s typically people’s second language – inherits whatever the pipeline hands it and exacerbates it further. In our sample, only 1.8% of Go developers identify as female, compared to 5.8% of Python developers.

Go vs Python developers

Gender

What is your gender?

GoPython
Male*Go 95.8%Python 90.8%
Female*Go 1.8%Python 5.8%
Non-binary, genderqueer, or gender non-conforming*Go 0.6%Python 1.2%
Prefer not to sayGo 1.8%Python 2.2%
Other*Go 0%Python 0.1%

Source: JetBrains Developer Ecosystem Survey 2026, weighted data. Base: Go n = 1,833, Python n = 11,284. Go and Python developers are respondents who selected the language among their primary languages; those who selected both are counted in both groups. * Statistically significant difference (p < 0.05, adjusted).

Transitioning from Python to Go

One-way path well traveled

You may ask why we’re focusing on transitioning from Python to Go, not the other way around. The data leaves little doubt about the path developers are taking. Python is already the most common second language among Go developers – 35% of Gophers declare it as their other primary language. But most Go developers (70%) say they have no intention of adopting another language in the next 12 months, and if they do, they name Rust (16%), rather than Python (2%). On the other hand, 10% of Python developers (a much larger cohort in terms of absolute numbers) plan to pick up Go, roughly 5.5 times the rate at which Go developers plan to pick up Python.

Go vs Python developers

Languages they plan to adopt in the next 12 months

Do you plan to adopt or migrate to other languages in the next 12 months? If so, which ones?

GoPython
Not planning to adopt any other language*Go 70%Python 61%
Rust*Go 16%Python 13%
Go*Go n/aPython 9%
C++*Go 3%Python 5%
Java*Go 2%Python 4%
Swift*Go 2%Python 4%
TypeScript*Go 2%Python 4%
Kotlin*Go 2%Python 4%
C#*Go 2%Python 3%
JavaScript*Go 1%Python 3%
CGo 2%Python 2%
SQL*Go 1%Python 3%
Python*Go 2%Python n/a
RubyGo 1%Python 2%
Shell scripting languages*Go 1%Python 2%
PHPGo 1%Python 1%
ElixirGo 2%Python 1%
DartGo 1%Python 1%
R*Go <1%Python 2%
HTML / CSS*Go <1%Python 2%
LuaGo 1%Python 1%
Assembly*Go <1%Python 1%
ScalaGo 1%Python 1%
MATLAB*Go <1%Python 1%
HaskellGo 1%Python <1%
Julia*Go <1%Python 1%
Visual Basic*Go <1%Python 1%
Platform-specific language (Apex, ABAP, 1C, etc.)*Go <1%Python 1%
PerlGo <1%Python <1%
COBOL*Go <1%Python <1%
GroovyGo <1%Python <1%
Objective-C*Go 0%Python <1%
LabVIEW*Go <1%Python <1%
F#Go <1%Python <1%
Delphi*Go 0%Python <1%
Clojure / ClojureScript*Go <1%Python <1%
CoffeeScript*Go 0%Python <1%
AdaGo <1%Python <1%
OtherGo 3%Python 2%

Source: JetBrains Developer Ecosystem Survey 2026, weighted data. Base: Go n = 1,836, Python n = 11,295. Go and Python developers are respondents who selected the language among their primary languages; those who selected both are counted in both groups. Multiple answers allowed. n/a: respondents already use this language as a primary one. * Statistically significant difference (p < 0.05, adjusted).

Why make the switch from Python to Go?

Despite working in different roles and on different products, the developers we interviewed gave consistent reasons for transitioning from Python to Go. These were:

  • Better performance and speed, including cold starts, latency, and operating cost.
  • Easier and more effective concurrency model.
  • Type safety that catches failures that would otherwise reach production at compile time.
  • Proximity to the platform, since Kubernetes and much of the cloud-native toolchain are written in Go, so teams working on that infrastructure already interact with Go daily.

What they gained and what they lost

Perceived potential gains are one thing, but did Go actually deliver? According to the developers we interviewed, it did in the areas described above. But they also found benefits they weren’t expecting: predictable formatting and linting that contributed to “clean code”, out-of-the-box tooling, and simplicity comparable to Python’s.

But Go also has flaws that are obvious to developers coming from Python. Just like the reasons for adopting Go were consistent, so were the complaints:

  • Explicit error handling that’s fundamentally different from Python, less intuitive, and more repetitive.
  • Overall verbosity and opinionatedness, with more lines needed to convey the same behavior and fewer ways to express it.
  • An object model that makes testing and mocking noticeably more difficult.
  • Library gaps, especially for testing.

Did they really leave?

“Migrating”, “transitioning”, and “switching over” may all sound like final decisions to leave Python behind, but that’s not really the case. Not one of the developers we interviewed removed Python from their stack completely. They kept it for artificial intelligence and machine learning, data science, and pipelines on platforms that only support Python, as well as simply because they work on larger teams that already know Python and are productive in it.

The realistic outcome of “moving to Go” is not becoming a monoglot, but having a polyglot codebase where each language is used for what it’s best suited for.

Conclusions

So, which language should you choose? Is it worth dropping Python in favor of Go? We hope that by now the answer is clear – it’s not a matter of which language is better, but which one is a better fit. Based on our data and developer testimony, here’s what we found.

Go may be a better fit if:

  • Performance is crucial for your app: Latency, throughput, or cold starts are problems you actually have and can measure.
  • The workload is concurrent, especially if it is I/O-heavy.
  • The service is long-lived and maintained by a team, not one person.
  • The system already depends heavily on Kubernetes and the rest of the cloud-native toolchain.

Python may be a better fit if:

  • The work is machine learning, data science, or numerical computing.
  • Your platform only accepts Python, as managed ETL and notebook environments frequently do.
  • Iteration speed matters more than runtime speed, which is often the case for internal tooling and prototypes.
  • The library you depend on has no Go equivalent; for a lot of the scientific stack, there isn’t one.

Language features alone rarely determine the best choice. When deciding what to build with, the teams weigh in the toolchain they already run, the languages their colleagues already know or are willing to learn, and how much of the existing system they are willing to change. Those things carry more weight than any benchmark, and they are why developers we talked to ended up using both languages, instead of choosing one.

Frequently asked questions

Can Go replace Python completely?

For a lot of backend work, yes, in principle. In practice, it doesn’t. None of the developers we interviewed removed Python from their stack completely. They kept it for machine learning and data science, for pipelines on platforms that only accept Python, and because the teams around them already know it. In the Developer Ecosystem 2026 survey, about a quarter of Go developers report using Python in the same project.

Is Go good for data engineering?

It depends on which end of the pipeline you mean. Go works well for moving data around, including ingestion services, stream processing, API integrations, and CLI tooling, and 30% of Go developers report working on data processing and analytics, compared with Python’s 38%. The analytical end is a different story: Only 15% of Gophers do data science and data analytics, against 32% of Python developers, and the library ecosystem reflects that.

How long does it take a Python developer to learn Go?

Days to weeks for the language itself. The syntax is small, gofmt settles the formatting arguments, and developers we talked to said Go “feels as easy to write as Python”. What takes longer is everything around it: system concepts such as pointers, interfaces, goroutines, and channels, as well as the habits Go asks you to change, from explicit error handling to designing test seams instead of patching at runtime.

The bigger adjustment may not be the language after all. Go work tends to sit closer to Kubernetes, Terraform, and GitOps, so if you’re moving into a Go team from a Python one, budget as much time for learning the toolchain as for the syntax.

Is Go good for machine learning?

For training models, probably not. 20% of Go developers work on artificial intelligence and machine learning, against 36% of Python developers, and the developers we interviewed were blunt about why: Python has the libraries, while Go lacks equivalents.

When it comes to building products around the models, it’s a different story. 46% of Go developers implement AI integrations, against Python’s 44% – a negligible difference. Gophers generally aren’t training the models, but they sure are serving them.

Can Go and Python be used in the same project?

Not only can they be used together, they often are. 27% of Go developers report using Python alongside Go in the same project, behind TypeScript (43%) and just ahead of JavaScript (24%). We know from interviews that the usual division of labor follows each language’s strengths: Go for the networked services and infrastructure, Python for data work, machine learning, and anything that depends on the scientific library stack.

Read the whole story
alvinashcraft
32 minutes ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories