Normal view

Template-based data extraction is dead. Here’s what comes next.

Abstract digital landscape featuring a dark teal 3D wireframe mesh mountain range and pixelated data grid terrain under fine geometric lines.

Modern businesses are in a constant, uphill battle against what to do with unstructured data: PDFs, contracts, scanned images, customer call recordings, meeting videos, and more. Traditional document automation workflows that rely heavily on template-based extraction or rigid rules used to make sense. But document formats have changed; they’re diverse and don’t fit standard formats, making costly, brittle, traditional systems a relic of the past. 

“Modern businesses are in a constant, uphill battle against what to do with unstructured data.”

Enterprises demand faster, more accurate processing, which raises the question: How can we reliably turn messy, multimodal content into structured, actionable insights without a mountain of manual effort?

That’s where Amazon Bedrock Data Automation (BDA) comes in.

What is Amazon Bedrock Data Automation (BDA)?

Amazon Bedrock Data Automation (BDA) is a generative AI-powered, fully managed service on Amazon Web Services for end-to-end document and media automation. It enables users to automate the extraction, classification, and transformation of unstructured content across modalities such as documents, images, audio, and video.

“At its core are Foundation models which enable intelligent extraction and understanding of content.”

At its core are Foundation models (FMs) which enable intelligent extraction and understanding of content. It allows users to configure standard output for common use cases, or even define custom extraction logic using blueprints tailored to your business. BDA is designed for scalability, accuracy, and auditability, making it ideal for enterprise workflows.

Walk-through: creating a project, standard output & custom output using blueprints

1. Create a project via console

In the Amazon Bedrock Console, navigate to Data AutomationCreate Project.

The Data Automation → Create Project interface in Amazon Bedrock.

Enter the name of the project:

The window to create a new BDA project.

2. Standard output:

Standard output gives you the model’s default, unstructured response (text, image, audio, or video) directly from the Data Automation pipeline.

The standard output from the Data Automation pipeline.

In standard output, each modality has its own options for what is needed as an output. 

Document:

The document modality options within the standard output tab.

Image & Video:

Image and video modality options.

Audio:

Audio modality options.

Now let’s test Document Modality for Standard Output:

First, click on “Test” in the upper right corner.

The document processing interface within Data Automation.

Next, select the document from the system, sample, or S3 and choose the modality from the dropdown menu. 

Test document processing interface

Click on the “Generate results” button:

The "generate results" button within the test document processing pane.

After processing, it will show the summary and content of the document:

Post-processing summary of the document, with the "document attributes" tab shown.

Post-processing summary of the document, with the "page level" tab shown.

Post-processing summary of the document, with the "element level" tab shown.

Custom output (blueprints):

Custom output lets you define a structured, predictable format using blueprints, which ensures the output matches your exact schema, fields, and business rules.

Let’s test custom output using blueprints for the same document:

Navigate to “Custom output” and click on “Add Blueprint”:

The custom output tab in the test document processing interface of Amazon Bedrock.

From here, two options will appear. You can either use LLM power to generate the blueprint (where it inspects the document), or you can choose to enter field names, instructions, and other information manually.

The "Create blueprint" pane within the custom output setup.

Below is a blueprint generated by LLM which has pulled all possible fields and tables from the document:

Image showing a blueprint generated by an LLM.

It has extracted the information using the blueprint as demonstrated below, including the  Field name, Instruction, and Results:

A summary table showing all extracted information using the blueprint.

It also provides the Extraction type (which can be Explicit or Inferred), Confidence percentage, and other relevant information.

Image showing the type of each instance of extracted information.

Additionally, it can extract information in the form of a table, such as an account summary or transaction information:

Extracted information in the form of a table; in this case, an account summary of the example bank statement.

Code examples

Amazon Bedrock Data Automation (BDA) Utility Module
Description:
    Helper functions to create BDA projects, blueprints, invoke jobs,
    monitor job status, and fetch results.
import boto3
import time
import json
import botocore
class BedrockDataAutomation:
    def __init__(self, region="us-east-1"):
        self.bda = boto3.client("bedrock-data-automation", region_name=region)
        self.runtime = boto3.client("bedrock-data-automation-runtime", region_name=region)

    # ------------------------------------------------------------
    # BLUEPRINT OPERATIONS
    # ------------------------------------------------------------
    def create_blueprint(self, name, schema, description="", stage="LIVE"):
        """
        Create a BDA Custom Output Blueprint from a JSON schema.
        """
        print(f"Creating blueprint: {name}")

        response = self.bda.create_blueprint(
            blueprintName=name,
            blueprintStage=stage,
            type="DOCUMENT",
            schema=json.dumps(schema)
        )
        return response["blueprint"]["blueprintArn"]

    # ------------------------------------------------------------
    # PROJECT OPERATIONS
    # ------------------------------------------------------------
    def create_project(self, name, description, standard_output_config, custom_output_config=None):
        """
        Create a BDA Project with Standard or Custom Output.
        """
        print(f"Creating project: {name}")

        response = self.bda.create_data_automation_project(
            projectName=name,
            projectDescription=description,
            projectStage="LIVE",
            standardOutputConfiguration=standard_output_config,
            customOutputConfiguration=custom_output_config or {}
        )
        return response["projectArn"]

    # ------------------------------------------------------------
    # INVOCATION OPERATIONS
    # ------------------------------------------------------------
    def invoke_project(self, project_arn, profile_arn, input_s3_uri, output_s3_uri, blueprints=None):
        """
        Invoke a BDA project using async invocation.
        """
        print(f"Invoking project: {project_arn}")

        kwargs = {
"inputConfiguration": {"s3Uri": input_s3_uri},
"outputConfiguration": {"s3Uri": output_s3_uri},
"dataAutomationConfiguration": {
"dataAutomationProjectArn": project_arn,
"stage": "DEVELOPMENT"
},
"dataAutomationProfileArn": profile_arn
}

        if blueprints:
kwargs["blueprints"] = blueprints

        response = self.runtime.invoke_data_automation_async(**kwargs)
       invocation_arn = response["invocationArn"]

       print("Invocation ARN:", invocation_arn)
       return invocation_arn

    # ------------------------------------------------------------
    # JOB STATUS POLLING
    # ------------------------------------------------------------
    def wait_for_job(self, invocation_arn, poll_interval=10):
        """
        Poll until job finishes.
        Returns final status object.
        """
        print("Polling job:", invocation_arn)

        while True:
            try:
                resp = self.runtime.get_data_automation_status(
                    invocationArn=invocation_arn
                )
            except Exception as e:
                print("Error fetching status:", e)
                raise

            status = resp["status"]
            print(f"Status: {status}")

            if status in ("SUCCEEDED", "FAILED", "CANCELLED"):
                return resp

            time.sleep(poll_interval)



# --------------------------------------------------------------------
# EXAMPLE USAGE
# --------------------------------------------------------------------
if __name__ == "__main__":
    bda = BedrockDataAutomation(region="us-east-1")

    # 1. Create Blueprint
    blueprint_schema = {
        "type": "object",
        "properties": {
            "account_holder": {"type": "string"},
            "balance": {"type": "string"},
            "transactions": {
                "type": "array",
                "items": {
                    "type": "object",
                    "properties": {
                        "date": {"type": "string"},
                        "description": {"type": "string"},
                        "amount": {"type": "string"}
                    }
                }
            }
        },
        "required": ["account_holder", "transactions"]
    }

    blueprint_arn = bda.create_blueprint(
        name="BankStatementBlueprint",
        schema=blueprint_schema,
        description="Extract fields from bank statements."
    )

    # 2. Create Standard Output Config
    standard_config = {
        "document": {
            "extraction": {
                "granularity": {"types": ["PAGE", "LINE"]},
                "boundingBox": {"state": "ENABLED"}
            },
            "outputFormat": {
                "textFormat": {"types": ["PLAIN_TEXT", "CSV"]}
            }
        }
    }

    # 3. Create Project with Custom Blueprint
    project_arn = bda.create_project(
        name="BankStatementProject",
        description="Process PDF bank statements",
        standard_output_config=standard_config,
        custom_output_config={
            "blueprints": [
                {
                    "blueprintArn": blueprint_arn,
                    "blueprintStage": "DEVELOPMENT",
                    "blueprintVersion": "1"
                }
            ]
        }
    )

    # 4. Invoke the project
    # Ensure you replace <ACCOUNT_ID> with your actual AWS Account ID
    profile_arn = "arn:aws:bedrock:us-east-1:<ACCOUNT_ID>:data-automation-profile/us.data-automation-v1"
    invocation_arn = bda.invoke_project(
        project_arn=project_arn,
         profile_arn=profile_arn,
        input_s3_uri="s3://your-bucket/input/statement.pdf",
        output_s3_uri="s3://your-bucket/output/",
        blueprints=[
            {
                "blueprintArn": blueprint_arn,
                "version": "1",
                "stage": "DEVELOPMENT"
            }
        ]
    )

    # 5. Poll job status
    final_status = bda.wait_for_job(invocation_arn)
    print("Final status:", json.dumps(final_status, indent=4))

Types of document blueprints

When processing documents, BDA supports five core automation types:

1. Classification: invoice, bank statement, ID card, contract, HR letter, etc.

2. Extraction: Extract entities, fields, tables, metadata.

  • Example: From a bank statement → Date, Description, Amount, Balance.

3. Transformation: Modify or restructure data.

  • Example: Convert Home Address into separate fields -> street, city, ZIP code, etc.

4. Normalization: Standardize data values.

  • Example: Convert multiple date formats (MM/DD/YYYY → YYYY-MM-DD).

5. Validation: Validate extracted fields against rules.

  • Example: Amount must be numeric; dates must match the format; balances must reconcile.

Use cases that illustrate business value

Real-world scenarios where BDA provides significant ROI include:

  • Financial Services: Automate processing of bank statements, invoices, and loan applications, reducing manual labor and speeding up reconciliation or underwriting.
  • Insurance: Ingest and extract data from claims forms, medical reports, and damaged-asset photos.
  • HR / Legal: Process resumes, contracts, and offer letters; extract structured data, including skills, clauses, salaries, and parties.
  • Customer Support: Transcribe and summarize calls, extract intent and sentiment, and feed those insights into CRM or case systems.
  • Security & Compliance: Analyze CCTV footage or meeting recordings to detect key actions, summarize context, and flag compliance issues.

BDA proves itself flexible and powerful, as it supports both standard outputs for basic workflows and fine-tuned custom schemas via blueprints. It is scalable and robust, with projects that enable batch processing and versions (development vs. live) for safe testing. It’s also audit-friendly, providing structured fields with types, normalization rules, and validation logic. 

“Compared with rule-based systems, foundation models achieve better semantic extraction across the board.”

A true key benefit is that BDA is multimodal across formats. Users can use the BDA framework to process documents, images, audio, and video. And, best of all, it’s highly accurate. Compared with rule-based systems, foundation models achieve better semantic extraction across the board. 

Amazon Bedrock Data Automation empowers businesses to transform unstructured, multimodal content into structured, trustworthy, and actionable data. With minimal setup, highly customizable blueprints, and a scalable project-based architecture, BDA helps organizations reduce manual workload and unlock insights faster.

The post Template-based data extraction is dead. Here’s what comes next. appeared first on The New Stack.

Kubernetes teams trust automation to ship code but not to touch CPU, and AI is raising the stakes

Kubernetes teams automate deployments without thinking about it. CI/CD pipelines fire dozens of times a day, autoscaling adjusts replicas in the background, rollback is muscle memory. But there is one category of automation where that confidence vanishes: letting a system change CPU and memory requests on a running workload without a human reviewing it first. 

And as AI inference lands on Kubernetes at scale, that hesitation is becoming hard to ignore, and increasingly expensive.

Why teams trust automation for change but not for constraint

We surveyed 321 Kubernetes practitioners at enterprise organizations earlier this year. The headline finding is one most practitioners will recognize immediately: 82% report high or complete trust in automated delivery controls. But 71% still require human review before applying resource optimization recommendations. Only 27% allow CPU and memory changes to be auto-applied, even within guardrails.

“Deploying code feels additive… rightsizing feels subtractive because you are removing safety margin from a running service, and the failure mode is fundamentally different.”

Those numbers describe a specific asymmetry. The same engineers who deploy to production dozens of times a day without hesitation slow down the moment automation wants to adjust resource allocation. And the survey data make it clear why. Deploying code feels additive. You are shipping new value, the rollback path is well understood, and if something breaks you usually see it right away. Meanwhile, rightsizing feels subtractive because you are removing safety margin from a running service, and the failure mode is fundamentally different.

As one practitioner in the survey put it: “Automated right-sizing carries a unique risk because it directly impacts the underlying stability of the application runtime. Unlike a code deployment that follows a tested path, resource changes alter the invisible contract between the workload and the scheduler.”

When you change resource requests, you change how Kubernetes schedules, prioritizes, and allocates resources. Those effects are not visible the way a code change is. You can’t trace them through a deployment pipeline. And you might not discover that something went wrong until two weeks later, when a traffic spike hits a threshold that didn’t exist at the old values. By that point, three other things have changed too, and proving causation is nearly impossible. The people responsible for those workloads are the same people who get paged at 2 a.m., and they know this.

Why AI workloads raise the stakes

That trust gap existed before inference workloads showed up. What’s changed is the cost of not closing it.

For a long time, teams could absorb the cost of manual oversight. They knew their workloads, had intuition for where the safe boundaries were, and the inefficiency of over-provisioning was a price worth paying for stability. GPU-accelerated inference workloads change that math. GPU compute is significantly more expensive per hour than CPU. The cost of over-provisioning is no longer a rounding error you can absorb quietly. And the workload behavior is less familiar, as inference jobs are bursty in ways teams haven’t built intuition for, traffic patterns shift as models are updated and usage changes, and the resource dimensions involved differ from what teams have spent years learning to tune.

That unfamiliarity compounds with scale. Rightsizing isn’t a one-lever problem the way horizontal scaling is. It involves, at minimum, CPU and memory requests and potentially limits for both, with four dimensions per workload, multiplied across hundreds or thousands of workloads per cluster. The survey data indicates that manual optimization breaks down at around 250 changes a day. Inference workloads push teams past that threshold faster than anything they’ve managed before, because the resource decisions are more frequent and the cost of getting them wrong is higher.

The economic case for automated rightsizing has never been stronger. The organization’s willingness to delegate hasn’t caught up because teams are being asked to trust automation with workloads they don’t yet have a track record with.

What the survey says about closing the gap

When we asked practitioners what would actually increase their trust in optimization automation, 48% said visibility and transparency into how decisions are made, 25% wanted proven guardrails, and 23% needed instant rollback.

Nobody asked for full manual control and very few asked for blind autonomy. What they described is automation that earns trust in stages, and that’s consistent with how the teams furthest along in their automation journey actually got there. They didn’t start with production. They started with a single namespace in a dev environment, observed the system’s behavior, compared recommendations with outcomes, and gradually expanded the scope. Different environments remained at different levels of automation maturity simultaneously, and that was intentional. Production carried more scrutiny than dev.

CI/CD followed the same curve, and the timeline is easy to forget. Most organizations took years to get from running their first automated pipeline to trusting it with production deploys without manual approval on every commit. Kubernetes resource automation is earlier in that same process, and AI workloads are extending the timeline because teams are building trust from scratch with a workload category that doesn’t yet have a track record.

Why automation design matters as much as capability

Some automation architectures deliver meaningful value only with full delegation. The system needs complete control to function the way it was designed to. That’s a form of forced autonomy, and it creates an adoption problem because it asks for exactly the level of trust that most organizations haven’t built yet. Force generally doesn’t work. Teams that feel pushed into a level of delegation they aren’t comfortable with tend to pull back entirely after the first incident.

The alternative is what I’d describe as adaptive autonomy: designing the system to work at every stage of the trust curve. A team still evaluating gets useful recommendations in read-only mode. A team ready to act but wanting boundaries can run guardrailed execution within limits they define. As confidence grows, the system handles more decisions autonomously while humans manage exceptions. And for environments where the track record supports it, closed-loop optimization runs in the background and becomes boring, which is the goal. Each stage is a legitimate operating mode, not a stepping stone you have to rush through.

That design distinction matters more with AI workloads than it ever did with traditional services, precisely because the trust-building process is starting from zero on workloads where the cost of getting it wrong is highest.

“Trust takes a long time to build and a single production incident to undermine.”

The other piece that makes this sustainable is rollout safety. Trust takes a long time to build and a single production incident to undermine. Start with the workloads showing the most headroom between requests and actual usage. Make changes incrementally, small enough that a bad outcome stays contained. Rollback needs to be fast and tied to the health signals the team already monitors. And start with opt-in, not opt-out. Let the teams willing to go first build a track record that others can look at.

The broader pattern

The 71% figure is sometimes read as resistance to automation. I think it’s a more accurate picture of how operational trust actually forms: conditional, earned over time, and moving at different speeds depending on what’s at stake. AI workloads are raising those stakes significantly, which means the path to trusted automation matters more now than it did when the cost of caution was just some unused CPU.

“Most of what gets written about Kubernetes optimization focuses on tooling capability, and the tooling is capable. The harder problem is the human one.”

Most of what gets written about Kubernetes optimization focuses on tooling capability, and the tooling is capable. The harder problem is the human one. If your team is managing AI inference workloads on Kubernetes and your optimization tooling is sitting in read-only mode, the question worth asking isn’t whether to trust the system. It’s whether the system is designed to let you build that trust gradually, starting where the stakes are low and expanding as the evidence supports it, on workloads where getting it wrong costs more than it ever has before.

The post Kubernetes teams trust automation to ship code but not to touch CPU, and AI is raising the stakes appeared first on The New Stack.

GitLab just surveyed 1,500 developers. Here’s why it matters for your codebase.

Minimalist geometric illustration of a solitary person straining against a rope. This perfectly visualizes the core insight that rapid AI coding speed without infrastructure control and governance becomes a major organizational liability.

For the past two years, the conversation about AI-assisted software development has been dominated by speed. A new GitLab survey of more than 1,500 developers and technology leaders found that 60% say AI coding ROI has already exceeded expectations, and 78% report their teams are writing and committing code faster since adopting AI tools. 

But speed without control is a liability.

Most organizations have pursued agentic engineering by adding AI coding tools on top of their existing infrastructure. Coding agents are delivering speed, but that speed isn’t showing up across the full software lifecycle: Only 21% of respondents report productivity gains beyond code generation itself.

“Speed without control is a liability.”

The infrastructure problem runs deeper. Git backends, toolchains, and governance frameworks were built for human-scale concurrency. Agents operate at machine scale, and that mismatch shows up fast. Platform reliability breaks down with millions of agent sessions hitting the same backend, security exposure widens as agents touch dependencies at scale, and cost overruns mount as agents consume tokens inefficiently on infrastructure that wasn’t built for them.

Agentic adoption outpaced governance

The adoption curve for AI coding tools outpaced the development of required guardrails, with 80% of organizations saying they adopted AI tools faster than they developed policies to govern them, and 82% reporting that AI-generated code risks creating a new form of technical debt that their organizations are not prepared to manage.

In practice, that means platform reliability challenges under agent load, security and compliance exposure that widens as agents touch dependencies at volume, and agents operating with artificial confidence because they lack full context. Only 28% of organizations say their software development lifecycle tools are fully integrated with shared data and workflows, which means most teams are trying to govern agent actions across a toolchain that was never designed for them.

Agentic engineering needs agentic infrastructure

Agentic engineering requires two things: agentic coding and agentic infrastructure. Most organizations have the first but lack the second.

Agentic infrastructure spans four areas: the execution layer, the context layer, the governance layer, and the orchestration layer working together.

The first is machine-scale execution. Git backends, CI/CD pipelines, and deployment systems were designed for human-paced development. In the agentic era, they need to handle millions of agent sessions without breaking. When a production incident occurs, the path from symptom back to origin should take minutes, not days.

The second is context that travels with code. As Bastian Stahmer, Business Owner of Vehicle Software Development Platform at Mercedes-Benz, put it on a panel recently, “An agent can only be as good as the context and semantics fed to it.” A context graph connecting code, work items, pipelines, security findings, and production signals is what makes agents genuinely useful at scale and keeps artificial confidence in check.

“An agent can only be as good as the context and semantics fed to it.”

The third is governance built into the flow. Agent actions need to be tied to an identity, logged against a policy, and provable to a reviewer. Low-risk changes move fast, while higher-risk changes trigger review. For Mercedes, operating under automotive regulatory standards that require full traceability and human accountability, GitLab is the control plane where that accountability lives.

The fourth is orchestration. Execution, context, and governance are only as effective as the system coordinating them. The orchestration layer coordinates agent actions across the full software lifecycle according to the policies teams define, determining which agents run, in what order, and how failures and handoffs are managed. Without it, agentic infrastructure is a set of independent capabilities rather than a working system.

What’s next

The next phase of AI in software will focus less on generating code and more on governing it, according to 85% of respondents. That shift reflects how enterprises are maturing their thinking about AI, from a productivity tool to a foundational capability that needs to be trusted, traced, and maintained at scale.

When governance is built into the platform, speed and control are no longer in tension. Traceability becomes a competitive advantage. Context becomes institutional memory. And the codebase, rather than accumulating invisible risk, becomes an asset that grows more reliable over time.

The post GitLab just surveyed 1,500 developers. Here’s why it matters for your codebase. appeared first on The New Stack.

The database storage problem is solved. Here’s what comes next.

Abstract artistic wave pattern with flowing parallel lines in coral and purple, serving as a metaphor for Postgres database data movement and architectural pipelines.

For most of its 30-year history, Postgres has been viewed as a transactional database. Organizations trust it with customer records, financial transactions, and countless other operational workloads. Its reputation was built on reliability, strong transactional guarantees, and a vibrant open-source community that has spent decades refining the database without compromising its foundations.

However, some of the most important innovations in the Postgres ecosystem today have little to do with storing data. They have to do with reducing the need to move it around.

“Some of the most important innovations in the Postgres ecosystem today have little to do with storing data. They have to do with reducing the need to move it around.”

Database innovation has historically focused on performance, scalability, and reliability. Increasingly, the harder problem is interoperability: how operational data can be shared across analytical systems, AI applications, and downstream services without creating yet another pipeline or copy.

Why Postgres keeps showing up

The reality of modern software architecture is that data rarely stays in one place. Information created in operational systems quickly finds its way into warehouses, search platforms, machine learning environments, and AI applications. Every new system solves a legitimate business problem, but it also creates another destination for data and often another copy to maintain.

The costs of this approach extend beyond infrastructure spending alone. Every additional copy introduces latency, creates another potential source of inconsistency, and increases the operational burden of keeping systems synchronized. Many organizations now spend as much effort moving data as they do storing it.

“Many organizations now spend as much effort moving data as they do storing it.”

For many businesses, Postgres serves as the system of record for customer interactions, transactions, application state, and other business-critical information. As organizations expand their analytical, machine learning, and AI capabilities, they are not looking to create another source of truth; rather, they’re looking for better ways to work with the one they already trust.

That shift is changing how Postgres fits into modern architecture. Historically, Postgres was viewed primarily as the place where operational data originated before being copied into downstream systems. Increasingly, organizations want those systems to work more seamlessly with operational data while reducing the pipelines, copies, and synchronization processes required to support them.

Technologies such as logical replication, change data capture, and foreign data wrappers have helped Postgres participate more directly in larger data ecosystems. As a result, organizations are no longer asking only whether Postgres can store their data. They’re instead asking how easily it can connect to everything around it.

That shift, from evaluating databases primarily on storage and performance to evaluating them on interoperability, may be one of the most important changes happening in the Postgres ecosystem today.

AI is exposing old problems

The recent focus on AI has brought renewed attention to data movement. AI didn’t create the problem. If anything, it exposed a limitation that has been quietly growing for years. For decades, organizations built architectures around the idea that data would move between systems through pipelines and periodic synchronization. That model worked because most analytical workloads could tolerate some degree of delay.

AI is changing those expectations. Many AI applications depend on access to current operational context. The challenge is not that organizations lack data. In many cases, they already have it. The challenge is that the data is spread across multiple systems, each with its own copy, latency profile, and synchronization process.

“AI is forcing organizations to confront a broader question: How many copies of the same data are actually necessary? The answer increasingly appears to be fewer than most architectures maintain today.”

As a result, AI is forcing organizations to confront a broader question: How many copies of the same data are actually necessary? The answer increasingly appears to be fewer than most architectures maintain today. As expectations around freshness rise, reducing unnecessary data movement becomes just as important as accelerating it. The underlying challenge is not new. AI has simply made it harder to ignore.

What’s next

The database industry spent decades solving storage. Databases became more reliable, storage became cheaper, and infrastructure became dramatically easier to operate. The next challenge is not where data lives, but how easily it can be shared across systems without introducing additional pipelines, copies, and synchronization overhead. Increasingly, the goal is not simply moving data faster. It is reducing unnecessary movement altogether.

Postgres has a habit of outlasting predictions about its replacement. For years, members of the community have joked that every year is “the year of Postgres.” The joke works because it keeps turning out to be true. 

Three decades after its creation, Postgres continues to adapt to new workloads, new architectural patterns, and new ways of building applications.

That longevity is not an accident. Enterprises continue to rely on Postgres because it provides a stable and trusted foundation for operational data.  While that foundation is unlikely to change, the scope of what organizations expect Postgres to do will continue to expand.  

As new workloads continue to emerge, much of the innovation will come through extensions that expand Postgres’s capabilities without sacrificing the stability that made it successful. In that sense, the future of Postgres may not be about reinventing the database itself, but continuously expanding what can be built on top of it.

The post The database storage problem is solved. Here’s what comes next. appeared first on The New Stack.

Why AI retrieval and ranking need more than vector search

Artistic illustration of a silhouette hiker journeying toward complex, layered mountain peaks under a glowing aurora sky, serving as a metaphor for moving beyond vector search to multi-dimensional AI retrieval architectures.

A recent GigaOm CxO Decision Brief explores how AI retrieval architectures are evolving beyond flat vector databases as organizations combine semantic search, ranking, personalization, and machine learning inference in production systems.

Vector search changed the AI infrastructure landscape by making semantic retrieval practical at scale. By converting text, images, and user behavior into embeddings, organizations could move beyond exact keyword matching and retrieve information based on meaning. But production AI systems rarely stop at vector similarity.

A real-world query often requires multiple signals to be evaluated simultaneously. Semantic relevance may be one factor, but so are structured attributes, business rules, personalization signals, freshness, access controls, recommendation logic, and machine-learned ranking models. As organizations move from AI experimentation to production-scale applications, the challenge is no longer simply finding similar items. It is in combining all of the signals that matter while maintaining low latency and operational simplicity. This is where tensors are attracting increasing attention.

While vectors represent information as a single dimension of numerical values, tensors provide a more general framework for representing and operating on complex, multi-dimensional data structures. They offer more control in how relevance is computed, allowing dense embeddings, sparse features, metadata, and model outputs to be evaluated together within a unified retrieval and ranking process. For organizations building large-scale retrieval systems, this raises an important architectural question: is a flat vector store sufficient, or does the next generation of AI applications require something more expressive?

“Tensors provide a more general framework for representing and operating on complex, multi-dimensional data structures.”

A new GigaOm CxO Decision Brief, “The Tensor Advantage in AI Search,” explores this question in depth.

Among the findings:

  • Production AI systems increasingly depend on combining semantic, lexical, behavioral, and business signals rather than relying on vector similarity alone.
  • Architectural fragmentation between vector databases, search engines, rerankers, and feature stores introduces latency, operational complexity, and synchronization challenges that become more significant as workloads scale.
  • Emerging retrieval models, including multi-vector and late-interaction approaches, place new demands on infrastructure that were not anticipated when first-generation vector databases were designed.
  • Tensor-native architectures provide an alternative approach by treating multidimensional data structures as first-class citizens rather than forcing them into simpler vector abstractions.

The paper also examines the infrastructure, operational, and organizational implications of these architectural choices, including benchmark data, deployment considerations, and the trade-offs engineering leaders should evaluate when planning future AI retrieval systems.

“Retrieval is evolving from a nearest-neighbor problem into a ranking and decision-making problem.”

As AI applications become more sophisticated, retrieval is evolving from a nearest-neighbor problem into a ranking and decision-making problem. Understanding the role tensors play in that transition may be one of the most important architectural discussions facing engineering leaders today.

Download the GigaOm CxO Decision Brief to explore the findings in full.

The post Why AI retrieval and ranking need more than vector search appeared first on The New Stack.

When your data model is the bottleneck: lessons from Medium’s feature store

Abstract neon blue and green wavy lines on a dark background, representing fluid data streams and a database latency bottleneck.

“Keep readers reading” is the not-so-simple goal of Medium’s recommendations system. To predict what’s most likely to appeal to a particular reader at any given time, Medium continuously processes user activity signals (stories read, recommendations shown, follows, likes, etc.). It then immediately correlates that with the steady stream of new articles, which is estimated at millions per month.   

Smart models and good inference logic are required, but that’s not enough. The data must be stored and retrieved quickly enough to remain relevant while the user is browsing. That’s the job of Medium’s feature store. And getting the data model right started to matter a lot as they scaled to 1M operations per second.

Andréas Saudemont, Medium Principal Software Engineer, recently walked through how the team identified the problem and what they built to fix it. If you’d rather watch than read, you have two options: Watch a short version from Monster Scale Summit or an extended follow-up webinar

The feature store and its role in Medium’s recommendation system

The feature store ties it all together, ingesting user activity and internal events and feeding them to the ML models that power recommendations. It’s what enables customization like the “For You” feed that greets logged-in users.

A screenshot of Medium's "For you" page.

Each feature is a property of an entity, usually a user or a story. Some are simple and static, like whether a user holds a paid membership. Others capture interaction history: which stories a user has read, what content they’ve recently been shown, etc.

The following diagram shows a highly simplified view of the Medium feature store architecture:

A diagram showing a a highly simplified view of the Medium feature store architecture.

The problem with a relational features data model

When they built their feature store years ago, Medium used relational features for cross-entity relationships. Unlike regular features, a relational feature can have multiple values for a given entity ID. Each value is defined by a relation ID (the ID of the related entity) and a timestamp recording when the event occurred.

For example, a “story users have read” feature is attached to the story entity type. It relates to the user entity type, and its values indicate whether/when a given user has read that story. 

Andréas shared the following schema diagram to explain the concept:

A schema diagram explaining the relational features data model.

Features sit at the center, each attached to an entity type and defined by name, version, and data type. Non-relational features are simply a feature, an entity ID, and a value. Relational features add a relation ID mapping to another entity type, plus the value itself and a timestamp.

This approach proved suboptimal from a data modeling perspective. Since relational features link two entity types, the data ends up split between two tables: one for the entity IDs and one for the values. That means you can’t get both in a single query. The first query retrieves only entity IDs (not their associated values) and relies on ALLOW FILTERING. A second query then runs for each entity ID to fetch its value. “If we have 1000 entity IDs for which we want to fetch values, then we have to run 1000 queries to fetch these values,” Andréas said.

Overrelying on ALLOW FILTERING made things worse. “This is bad,” Andréas said, referring to monitoring data showing that 90% of rows read via these queries were simply discarded. “This is just data that we don’t need. ALLOW_FILTERING should be an escape hatch, not our design pattern.”

“ALLOW_FILTERING should be an escape hatch, not our design pattern.”

Chart showing that overreliance on ALLOW FILTERING led to 90.2% of rows read via these queries being discarded.

The list feature model

So they reinvented their data model and shifted to a list-based feature model. Instead of splitting data across two tables, everything for a given entity lives in one place and is retrieved in a single query.

Like other features, a list feature is defined by its entity type, name, and optional version. What’s different is the value. While a non-relational feature has a single value, such as true or false, a list feature’s value is a collection of items, each containing a value and a timestamp. Item values can be of any data type; the feature store doesn’t enforce consistency within a list.

Diagram explaining the list feature concept.

For example, consider a user’s reading history. The entity is user, the feature name is reading history, the TTL is 6 months. After that TTL is reached, the data is automatically dropped by the database (since older history isn’t useful for recommendations). The list for a given user is a collection of story IDs and the timestamps at which they were read. The same story can appear multiple times, and multiple items can share the same timestamp.

Example list of a user's reading history, showing a collection of story IDs and the timestamps at which they were read.

A range of operations need to be supported. Create List and Delete List operations run at most a few times per day. Remove List Items with Value, which lets a reader scrub a specific story from their history so it stops influencing recommendations, runs at 1k-10k per second. Add List Items is higher still: every story read and every thumbnail shown to a user generates an event. Get List Items is the top, at 100k-1M operations per second.

Table showing the number of times various operations run per given timeframe.

“The Add List Items, and even more the Get List Items operations, are really the reasons why we need an efficient data store.”

“The Add List Items, and even more the Get List Items operations, are really the reasons why we need an efficient data store,” Andréas said.

Multiple items, one timestamp

Beyond raw efficiency, the new data model also had to support multiple items with the same timestamp. When Medium shows a user four story thumbnails simultaneously, all four presentation events share the same timestamp, but have distinct story IDs. If this isn’t handled correctly, primary key collisions occur.

The team’s solution was a single list_items table that stores everything.

Screenshot of the code for the list_items table which stores everything.

The partition key combines feature_key and entity_id, keeping all items for a given list together. All of user 123’s reading history is stored in one partition, retrieved in one query. The clustering key concatenates each item’s timestamp with an MD5 hash of its value. The hash is what makes same-timestamp items with distinct values possible. 

Relying on MD5 hashes for uniqueness raises its own set of questions, but in practice, the team hasn’t seen collisions. “The values that we are storing are sufficiently distinct, especially when you add the timestamp into the equation,” Andréas said. The table’s clustering order is set to descending so ScyllaDB can optimize for the typical read pattern (most recent N items) rather than leaving the application to sort afterward.

TTL to control storage costs

Storage cost is controlled entirely through ScyllaDB’s native TTL, with no cleanup logic required. Every row expires automatically based on its own timestamp plus the feature’s TTL duration. “We don’t have anything to do regarding that,” Andréas said. “Any row for which the TTL is expired will be considered deleted by ScyllaDB.” 

Storage plateaus for a steady write rate. When a feature is retired, its data drains away on its own. “That’s super useful for controlling our storage and usage costs.”

Chart showing storage usage/costs and number of item insertions against time

Implementing the list operations

Add List Items is a logged batch of INSERTs with atomicity guaranteed: all items land or none do. Each row carries its own TTL calculated from its timestamp, so older items expire sooner. Since items almost always carry a current timestamp, new entries append to the top of the partition, which is exactly where reads will look first.

The code to "Add List Items" - a logged batch of INSERTs with atomicity guaranteed.

Table showing the "list_items" table partition before and after running the Add List Items function.

Get List Items runs as a single-partition SELECT with a minimum timestamp and a row limit. “We run the query on a single partition,” Andréas said. “That’s the maximum efficiency that we can have.” The clustering key handles filtering and ordering directly. Post-processing is not required.

The code to "Get List Items" - a single-partition SELECT with a minimum timestamp and a row limit.

The "list_items" table partition before running the "Get List Items" function, the response received from the function.

Remove List Items with Value is the one operation that couldn’t be reduced to a single query. Because value isn’t part of the primary key, a direct filter isn’t feasible.

Code for the "Remove List Items with Value" function.

A local secondary index built specifically for this case first finds the matching item keys, then a batch DELETE removes them by primary keys.

The code to create a local secondary index which lists items by value.

“Using an index is really faster than a scan because the query is highly selective,” Andréas explained. “We have very few items in a given list that have the same values compared to the total number of items in a list. And thanks to the current structure, using a local secondary index is faster than a global index.”

The "list_items" table partition before and after running the "Remove List Items with Value" function.

Andréas shared another example. Starting with the original table partition, the goal is to delete all items with the value “storyC.” Using the local secondary index, the system first identifies the two rows containing that value. It then issues two DELETE statements using the item keys from those rows, which removes them from the list. The final operation, removing all list items, is even more straightforward.

“We can just drop the partition,” Andréas said, “and ScyllaDB does its magic. It just deletes all the rows for that partition, which means that it deletes all the items for the given list. And bonus point: it’s atomic. It’s either completing successfully or not changing anything at all.

The code for the "Remove All List Items" function.

The "list_items" table partition before and after running the "Remove All List Items" function.

ScyllaDB vs. DynamoDB performance

Medium implemented the list operations on top of both ScyllaDB and DynamoDB. The main goal was to benchmark how both databases compared on their actual production data. “Conceptually they are very close,” Andréas noted, “but they have significant differences in how they operate.”

For AddListItems, P50 latencies were low with both databases: ScyllaDB came in under 1.5ms, DynamoDB under 5ms. “DynamoDB is extremely fast, not as fast as ScyllaDB, but extremely fast at sub 5ms latency,” Andréas commented. Things got more interesting at the P95 and P99 latencies. ScyllaDB held steady at around 5-6 ms P95s, while DynamoDB ranged from 13-45 ms. ScyllaDB’s P99s were steady single-digit milliseconds, while DynamoDB’s ranged from 40- 120 ms.

Graphs showing AddListItem latencies.
AddListItem latencies: The blue line is DynamoDB; the purple line is ScyllaDB

It was a similar story for GetListItems. At P50, ScyllaDB clocked in at 1 ms, DynamoDB at around 3.5 ms. At P95, ScyllaDB held around 5-6 ms while DynamoDB spiked from 30 – 60ms. And at P99, ScyllaDB remained at ~30ms while DynamoDB ranged from 70 ms all the way up to 220 ms.

Graphs showing GetListItem latencies.
GetListItem latencies: The top blue line is DynamoDB; the lower purple line is ScyllaDB

“ScyllaDB is very fast, with very predictable performance, and that’s super important for us.”

One caveat: DynamoDB was running without an extra caching layer. “We expect that could have a significant impact for DynamoDB because of the high cache hit rate that we are seeing on the list,” Andréas said. “But we don’t have the data yet, so we cannot compare them.” His verdict for now: “ScyllaDB is very fast, with very predictable performance, and that’s super important for us.”

Key takeaways

One pleasant side effect of getting the data model right: Medium is now eager to use ScyllaDB for additional feature store workloads. Before, they were holding back because they didn’t want to build on the shaky relational feature foundation.

Reflecting on the path to this point, Andréas left the audience with this parting advice:

“If you have a suboptimal data model, you will have queries that are slow, that will scale badly. And most likely, you won’t be able to optimize that data model. You will have to define a new data model that will be better. So take time to think about your data model before you start the implementation, because once you have production data using your suboptimal data model, it’s too late.”

The post When your data model is the bottleneck: lessons from Medium’s feature store appeared first on The New Stack.

AI retrieval at scale is becoming a systems problem, not a tooling problem

Flat art illustration of a single winding road through a vast night desert landscape, serving as a visual metaphor for an integrated AI retrieval data pathway.

AI retrieval has moved well beyond embeddings and vector search. Early retrieval architectures focused primarily on semantic similarity. Still, production AI applications increasingly demand more from the retrieval layer: combining keyword matching, semantic retrieval, ranking, and real-time signals within a single request path.

Vector databases solved an important problem by making semantic retrieval practical. But production AI systems increasingly require more than retrieval alone. Customer-facing applications such as search, recommendations, and RAG must retrieve, filter, and rank results in real time while serving large user populations under tight latency constraints. 

As systems evolve toward conversational, research-oriented, and agentic workflows, retrieval performance, ranking quality, and architectural simplicity become increasingly important to maintaining relevance at scale.

In recently published research commissioned by Vespa, GigaOm explores how AI search platforms are evolving as organizations move beyond standalone vector search toward more integrated retrieval and ranking architectures. Rather than focusing purely on model quality, the report examines the operational and architectural trade-offs that emerge as AI workloads move into production.

GigaOm’s findings

AI retrieval architectures have become more fragmented over time. What begins as a straightforward search stack often evolves into a collection of loosely coupled systems: lexical search, vector retrieval, feature serving, reranking, synchronization pipelines, and model infrastructure. 

“What begins as a straightforward search stack often evolves into a collection of loosely coupled systems.”

GigaOm’s view is that the operational overhead of connecting and maintaining these layers is becoming a limiting factor in itself, slowing iteration cycles and making every relevance improvement dependent on coordinated changes across multiple systems.

One of the more interesting findings in the report is that consolidation is not framed primarily as a procurement exercise but as an engineering and systems design decision. GigaOm argues that teams increasingly pay for fragmentation through duplicated data movement, synchronization logic, operational maintenance, and cross-system tuning. 

The hidden cost is not simply infrastructure spend but the engineering effort required to keep retrieval pipelines aligned, rather than improving ranking quality, personalization, and user-facing AI capabilities.

“The hidden cost is not simply infrastructure spend but the engineering effort required to keep retrieval pipelines aligned.”

The report also suggests that platform convergence matters because modern retrieval workloads increasingly combine keyword search, vector retrieval, real-time features, and ML-based ranking in the same request path. 

GigaOm highlights architectures that bring these stages closer together to reduce latency, improve data freshness, and simplify experimentation, while acknowledging trade-offs such as concentration risk and migration complexity. 

Rather than recommending wholesale replacement, the report advocates a phased adoption approach, beginning with ranking and validation on production workloads before progressively consolidating retrieval capabilities.

Download a copy of the report.

The post AI retrieval at scale is becoming a systems problem, not a tooling problem appeared first on The New Stack.

❌