EF Core 10 Turns PostgreSQL into a Hybrid Relational-Document DB

Modern .NET applications increasingly need to store data that doesn’t fit neatly into relational tables, whether it’s per-tenant custom fields, evolving product attributes, or external API payloads. Before EF Core 10, handling this kind of flexible data meant awkward modeling workarounds, raw JSON text columns, or scattered NoSQL side-stores.

In this blog, I’ll show you how EF Core 10 introduces a powerful new way to map JSONB columns in PostgreSQL through Complex Types. Combined with PostgreSQL’s highly optimized JSONB storage engine, this enables clean modeling of flexible, schema-evolving data, without sacrificing performance or queryability. I’ll help you understand when JSONB is the right tool, how EF Core 10 improves JSON mapping, and best practices for designing hybrid relational-document models.

Why JSONB Matters

Traditional relational models break when your application needs to store:

  • Dynamic or tenant-specific fields
  • Hierarchical or nested attributes
  • Evolving structures that change frequently
  • External API payloads or metadata

This is exactly where PostgreSQL JSONB shines: you get schema flexibility, native indexing, fast querying, and full ACID guarantees, all inside a relational engine.

JSON vs JSONB in PostgreSQL

FeatureJSONJSONB
StorageTextBinary tree
Query performanceSlowFast
IndexesNoneGIN/GiST
Duplicate keysPreservedLast wins
Parse costPer queryOnce at insert

Rule of thumb: Always use JSONB unless you need to preserve formatting, then use JSON.

EF Core 10 Transforms JSON Mapping

Before .NET 10, JSONB mapping required owned entities, causing:

  • Confusing ownership semantics
  • Shadow primary keys
  • Verbose configuration
  • No support for ExecuteUpdate

The .NET 10 Solution: Complex Types

EF Core 10 introduces Complex Types, providing:

  • Value-type semantics
  • Cleaner configuration
  • Automatic nested collections
  • Full LINQ → JSONB translation
  • Bulk JSON updates with ExecuteUpdate
  • Optional complex types (Address?)

Configuration Example:

modelBuilder.Entity<Product>()
    .ComplexProperty(p => p.Specs, b => b.ToJson());

That’s it—EF Core handles nested structures automatically.

Querying JSONB in EF Core 10

EF Core now translates complex LINQ queries directly into PostgreSQL JSONB operators such as ->, ->>, @>.

Filter by JSON attribute

var items = await context.Products
    .Where(p => p.Specs.Brand == "Apple")
    .ToListAsync();

Filter by nested number field

var results = await context.Products
    .Where(p => p.Specs.RAM >= 16)
    .ToListAsync();

Query JSON arrays

var items = await context.Products
    .Where(p => p.Specs.Features.Contains("Waterproof"))
    .ToListAsync();

Bulk JSON Updates with ExecuteUpdate (EF Core 10)

EF Core 10 brings real bulk-update support for JSONB:

await context.Products
    .ExecuteUpdateAsync(s =>
        s.SetProperty(p => p.Metadata.Views,
                      p => p.Metadata.Views + 1));

Performance Comparison (10,000 rows)

ApproachTimeMemorySQL Statements
Load + SaveChanges5–10sHigh10,000
ExecuteUpdate100–200msLow1

This is a huge improvement for analytics counters, status updates, metadata changes, etc.

When JSONB Is the Right Choice

Use JSONB for data that is:

✔ Schema-flexible

Metadata, preferences, workflow definitions, configuration.

✔ Hierarchical

Nested objects or lists that don’t map well to relational tables.

✔ Frequently evolving

Dynamic fields that change without requiring migrations.

✔ Semi-structured or external

Webhook payloads, API responses, integrations.

✔ Snapshot-based

Audit trails, version history, revision logs.

When NOT to Use JSONB

Avoid JSONB for:

❌ Stable, core domain data

Relational columns are faster and enforce constraints.

❌ Foreign key relationships

JSONB cannot enforce referential integrity.

❌ Join-heavy workloads

JOINs on relational fields outperform JSON extraction.

❌ High-write OLTP workloads

Updating JSONB rewrites the entire document.

Indexing JSONB Correctly

Without indexing, JSONB queries degrade quickly.

GIN index (most common)

CREATE INDEX idx_specs_gin ON products USING gin (specs);

Expression index for a specific field

CREATE INDEX idx_brand ON products ((specs ->> 'Brand'));

Use GIN for containment queries and expression indexes for filtering specific keys.

Designing a Hybrid Schema (The Recommended Approach)

The strongest architectures combine relational and JSONB styles:

Relational columns for:

  • Stable fields
  • Frequently queried attributes
  • Joins and foreign keys

JSONB for:

  • Optional fields
  • Dynamic or tenant-specific attributes
  • Metadata, preferences, and workflows

Example model:

public class Product
{
    public int Id { get; set; }
    public string Category { get; set; } = null!;
    public decimal Price { get; set; }

    // Flexible layer
    public ProductSpecifications Specs { get; set; } = new();
}

This gives you schema safety and flexibility.

Performance Summary

JSONB is Faster For:

  • Containment queries (@>)
  • Reading entire documents
  • Avoiding a few table joins

JSONB is Slower For:

  • Aggregations on large datasets
  • Frequent updates to large documents
  • Complex JOIN logic
  • Queries needing strict relational constraints

Practical Example: EF Core Configuration

modelBuilder.Entity<Order>(entity =>
{
    entity.ComplexProperty(o => o.Metadata, b => b.ToJson());
    entity.ComplexCollection(o => o.Items, b => b.ToJson());
});

Query

var orders = await context.Orders
    .Where(o => o.Items.Any(i => i.UnitPrice > 100))
    .ToListAsync();

Bulk update

await context.Orders
    .Where(o => o.Metadata.Status == "Pending")
    .ExecuteUpdateAsync(s =>
        s.SetProperty(p => p.Metadata.Status, "Processing"));

Conclusion

EF Core 10 finally provides a clean, powerful, and first-class way to use PostgreSQL JSONB through Complex Types.

Key Takeaways

  • Complex Types are the new standard for JSON mapping in .NET 10
  • JSONB is ideal for flexible, evolving, hierarchical data
  • ExecuteUpdate improves performance for JSON updates
  • Use a hybrid relational + JSONB model for the best architecture
  • JSONB is powerful—but not a replacement for relational design

When used strategically, JSONB becomes one of the most effective tools available to .NET developers building modern, flexible applications.

If your team is considering PostgreSQL JSONB, evaluating a hybrid model, or planning a modernization effort, we can help you chart the right architecture and avoid the common pitfalls. Contact Trailhead to discuss your project. We love helping teams modernize successfully!

Picture of Stefan Mitic

Stefan Mitic

Stefan is an experienced .NET developer from Serbia with seven years in the software industry. Stefan earned his B.S. in Computer Science and at the Faculty of Electrical Engineering, University of Nis. Over the course of his career, he has contributed to various projects, including Geographic Information Systems (GIS), Enterprise Resource Planning (ERP) solutions, Warehouse Management Systems (WMS), and Product Information Management (PIM) systems. Driven by a passion for building high- performance software, he focuses on creating robust, efficient, and scalable solutions. His strengths lie in problem-solving and delivering reliable results. Beyond his professional pursuits, Stefan enjoys tennis, football, playing guitar, and playing chess.

Free Consultation

Sign up for a FREE consultation with one of Trailhead's experts.

"*" indicates required fields

This field is for validation purposes and should be left unchanged.

Related Blog Posts

We hope you’ve found this to be helpful and are walking away with some new, useful insights. If you want to learn more, here are a couple of related articles that others also usually find to be interesting:

Sentiment Analysis in C#: Azure AI Language or LLMs

Explore how C# developers can leverage both Azure AI Language and Azure OpenAI for sentiment analysis. This post compares traditional NLP services with LLM-based approaches using real-world code from an exit interview system, helping you choose the right tool for your specific use case.

Read More

Our Gear Is Packed and We're Excited to Explore With You

Ready to come with us? 

Together, we can map your company’s software journey and start down the right trails. If you’re set to take the first step, simply fill out our contact form. We’ll be in touch quickly – and you’ll have a partner who is ready to help your company take the next step on its software journey. 

We can’t wait to hear from you! 

Main Contact

This field is for validation purposes and should be left unchanged.

Together, we can map your company’s tech journey and start down the trails. If you’re set to take the first step, simply fill out the form below. We’ll be in touch – and you’ll have a partner who cares about you and your company. 

We can’t wait to hear from you! 

Montage Portal

Montage Furniture Services provides furniture protection plans and claims processing services to a wide selection of furniture retailers and consumers.

Project Background

Montage was looking to build a new web portal for both Retailers and Consumers, which would integrate with Dynamics CRM and other legacy systems. The portal needed to be multi tenant and support branding and configuration for different Retailers. Trailhead architected the new Montage Platform, including the Portal and all of it’s back end integrations, did the UI/UX and then delivered the new system, along with enhancements to DevOps and processes.

Logistics

We’ve logged countless miles exploring the tech world. In doing so, we gained the experience that enables us to deliver your unique software and systems architecture needs. Our team of seasoned tech vets can provide you with:

Custom App and Software Development

We collaborate with you throughout the entire process because your customized tech should fit your needs, not just those of other clients.

Cloud and Mobile Applications

The modern world demands versatile technology, and this is exactly what your mobile and cloud-based apps will give you.

User Experience and Interface (UX/UI) Design

We want your end users to have optimal experiences with tech that is highly intuitive and responsive.

DevOps

This combination of Agile software development and IT operations provides you with high-quality software at reduced cost, time, and risk.

Trailhead stepped into a challenging project – building our new web architecture and redeveloping our portals at the same time the business was migrating from a legacy system to our new CRM solution. They were able to not only significantly improve our web development architecture but our development and deployment processes as well as the functionality and performance of our portals. The feedback from customers has been overwhelmingly positive. Trailhead has proven themselves to be a valuable partner.

– BOB DOERKSEN, Vice President of Technology Services
at Montage Furniture Services

Technologies Used

When you hit the trails, it is essential to bring appropriate gear. The same holds true for your digital technology needs. That’s why Trailhead builds custom solutions on trusted platforms like .NET, Angular, React, and Xamarin.

Expertise

We partner with businesses who need intuitive custom software, responsive mobile applications, and advanced cloud technologies. And our extensive experience in the tech field allows us to help you map out the right path for all your digital technology needs.

  • Project Management
  • Architecture
  • Web App Development
  • Cloud Development
  • DevOps
  • Process Improvements
  • Legacy System Integration
  • UI Design
  • Manual QA
  • Back end/API/Database development

We partner with businesses who need intuitive custom software, responsive mobile applications, and advanced cloud technologies. And our extensive experience in the tech field allows us to help you map out the right path for all your digital technology needs.

Our Gear Is Packed and We're Excited to Explore with You

Ready to come with us? 

Together, we can map your company’s tech journey and start down the trails. If you’re set to take the first step, simply fill out the contact form. We’ll be in touch – and you’ll have a partner who cares about you and your company. 

We can’t wait to hear from you! 

Thank you for reaching out.

You’ll be getting an email from our team shortly. If you need immediate assistance, please call (616) 371-1037.