Database Integration for CPQ — Queryable Configuration History

Ignitionary reads and writes directly to SQL Server, PostgreSQL, MySQL, Oracle, and MongoDB via REST APIs and native drivers. Pull product data and pricing from the tables you already own at quote time, and write every configuration, quote, and option selection back as structured, queryable records — so your data team can report on what was configured, not just what was sold.

Built for IT and data teams who need configuration data in their own warehouse, on their own schema, with a clean audit trail.

What does database integration do for your IT and data team?

It keeps configuration data in systems you control — your schema, your warehouse, your governance — instead of locking it inside a black-box SaaS you can only export from as a CSV.

🗄️

Queryable configuration history

Every configuration, quote, and option choice is written back as structured rows you can query with SQL — so analysts answer "which options ship together" or "how did this SKU's price change" without waiting on a vendor export.

🔌

Reads from your source of truth

Product data, pricing tables, and part attributes are read live from the databases you already maintain, so there's no duplicate master to keep in sync and no migration project to stand up the configurator.

🧩

Fits your existing schema

SQL Server, PostgreSQL, MySQL, Oracle, or MongoDB — Ignitionary maps to your tables and naming conventions rather than forcing its own data model on you, so it drops into your stack instead of fighting it.

🔐

Governance & audit trail

Scoped credentials, TLS in transit, and a timestamped record of every configuration mean data governance and compliance can trace exactly what was quoted, by whom, and when.

With configuration history landing in your own warehouse, data teams turn quoting activity into a first-class analytics source — feeding demand forecasting, option-popularity analysis, and margin reporting without a single manual export.

Supported Database Systems

Native connectivity with major database platforms

SQL Server

Microsoft SQL Server, Azure SQL

  • • T-SQL stored procedures
  • • Connection pooling
  • • Encrypted connections
  • • Change data capture

PostgreSQL

PostgreSQL, Amazon RDS, Google Cloud SQL

  • • JSON/JSONB support
  • • Custom functions
  • • Full-text search
  • • Streaming replication

MongoDB

MongoDB Atlas, DocumentDB

  • • Document-based storage
  • • Aggregation pipelines
  • • Change streams
  • • Flexible schemas

Oracle & Others

Oracle, MySQL, MariaDB, Redis

  • • ODBC/JDBC connectivity
  • • Custom adapters
  • • Data warehousing
  • • Caching layers

Database API Endpoints

Key integration points for database connectivity

Product Data Management

GET /api/v1/products Retrieve product catalog from database
GET /api/v1/products/{id}/options Get configuration options and constraints
POST /api/v1/products/{id}/validate Validate configuration against database rules

Configuration Tracking

POST /api/v1/configurations Store configuration session data
GET /api/v1/configurations/analytics Retrieve configuration analytics and trends
PUT /api/v1/configurations/{id} Update saved configuration

Pricing & Inventory

GET /api/v1/pricing/calculate Calculate pricing from database rules
GET /api/v1/inventory/check Check component availability
POST /api/v1/quotes Generate and store quote in database

Authentication Requirements

  • Database connection credentials
  • SSL/TLS encryption for data transit
  • Role-based access control
  • Connection pooling and timeout handling

Implementation Examples

Sample code for common database integration scenarios

SQL Server Product Configuration Query

-- Stored procedure to get product configuration options
CREATE PROCEDURE GetProductConfigurationOptions
    @ProductID INT,
    @CustomerSegment VARCHAR(50) = NULL
AS
BEGIN
    SELECT
        co.OptionID,
        co.OptionName,
        co.OptionType,
        co.DefaultValue,
        co.MinValue,
        co.MaxValue,
        co.PriceModifier,
        CASE
            WHEN cs.CustomerSegment IS NOT NULL
            THEN cs.SegmentPriceModifier
            ELSE co.PriceModifier
        END AS EffectivePriceModifier
    FROM ConfigurationOptions co
    LEFT JOIN CustomerSegmentPricing cs
        ON co.OptionID = cs.OptionID
        AND cs.CustomerSegment = @CustomerSegment
    WHERE co.ProductID = @ProductID
        AND co.IsActive = 1
        AND co.EffectiveDate <= GETDATE()
        AND (co.ExpiryDate IS NULL OR co.ExpiryDate > GETDATE())
    ORDER BY co.DisplayOrder;
END

PostgreSQL Configuration Analytics

-- PostgreSQL function for configuration analytics
CREATE OR REPLACE FUNCTION get_configuration_analytics(
    start_date DATE,
    end_date DATE
) RETURNS TABLE(
    product_id INTEGER,
    product_name VARCHAR,
    total_configurations BIGINT,
    avg_configuration_value NUMERIC,
    popular_options JSONB
) AS $$
BEGIN
    RETURN QUERY
    SELECT
        p.id AS product_id,
        p.name AS product_name,
        COUNT(c.id) AS total_configurations,
        AVG(c.total_price) AS avg_configuration_value,
        jsonb_agg(
            jsonb_build_object(
                'option', co.option_name,
                'count', option_counts.option_count
            ) ORDER BY option_counts.option_count DESC
        ) AS popular_options
    FROM products p
    LEFT JOIN configurations c ON p.id = c.product_id
        AND c.created_at BETWEEN start_date AND end_date
    LEFT JOIN LATERAL (
        SELECT
            co.option_name,
            COUNT(*) AS option_count
        FROM configuration_options co
        JOIN jsonb_array_elements(c.selected_options) AS selected(option)
            ON (selected.option->>'id')::INTEGER = co.id
        GROUP BY co.option_name
        LIMIT 5
    ) option_counts ON true
    GROUP BY p.id, p.name;
END;
$$ LANGUAGE plpgsql;

MongoDB Configuration Storage

// Node.js MongoDB integration for configuration storage
const { MongoClient } = require('mongodb');

class ConfigurationDatabase {
  constructor(connectionString) {
    this.client = new MongoClient(connectionString);
    this.db = this.client.db('ignitionary');
  }

  async saveConfiguration(configData) {
    const configurations = this.db.collection('configurations');

    const document = {
      productId: configData.productId,
      customerId: configData.customerId,
      sessionId: configData.sessionId,
      selectedOptions: configData.options,
      totalPrice: configData.totalPrice,
      metadata: {
        timeSpent: configData.timeSpent,
        revisions: configData.revisions,
        source: configData.source
      },
      createdAt: new Date(),
      status: 'draft'
    };

    const result = await configurations.insertOne(document);
    return result.insertedId;
  }

  async getConfigurationTrends(productId, days = 30) {
    const configurations = this.db.collection('configurations');
    const startDate = new Date();
    startDate.setDate(startDate.getDate() - days);

    const pipeline = [
      {
        $match: {
          productId: productId,
          createdAt: { $gte: startDate }
        }
      },
      {
        $unwind: '$selectedOptions'
      },
      {
        $group: {
          _id: '$selectedOptions.optionId',
          optionName: { $first: '$selectedOptions.name' },
          count: { $sum: 1 },
          avgPrice: { $avg: '$selectedOptions.price' }
        }
      },
      {
        $sort: { count: -1 }
      },
      {
        $limit: 10
      }
    ];

    return await configurations.aggregate(pipeline).toArray();
  }
}

Real-time Database Synchronization

// Real-time price updates using database triggers
async function setupRealTimeSync() {
  // SQL Server Change Data Capture setup
  const sql = require('mssql');

  const config = {
    server: process.env.DB_SERVER,
    database: process.env.DB_NAME,
    user: process.env.DB_USER,
    password: process.env.DB_PASSWORD,
    options: {
      encrypt: true,
      enableArithAbort: true
    }
  };

  const pool = await sql.connect(config);

  // Monitor price changes
  const request = pool.request();
  request.stream = true;

  request.query(`
    SELECT * FROM cdc.fn_cdc_get_all_changes_dbo_ProductPricing(
      sys.fn_cdc_get_min_lsn('dbo_ProductPricing'),
      sys.fn_cdc_get_max_lsn(),
      'all'
    )
  `);

  request.on('row', async (row) => {
    // Update configurator cache with new pricing
    const productId = row.__$start_lsn;
    const operation = row.__$operation;

    if (operation === 2 || operation === 4) { // Insert or Update
      await updateConfiguratorPricing(productId, row);

      // Notify active configurator sessions
      await notifyActiveConfigurators(productId, {
        type: 'price_update',
        productId: productId,
        newPrice: row.Price
      });
    }
  });
}

async function updateConfiguratorPricing(productId, priceData) {
  // Update Redis cache or application state
  const redis = require('redis');
  const client = redis.createClient();

  await client.setex(
    `pricing:${productId}`,
    3600, // 1 hour cache
    JSON.stringify(priceData)
  );
}

Recommended Database Schema

Core tables for configuration management

-- Core tables for configuration management
CREATE TABLE Products (
    ProductID INT PRIMARY KEY,
    ProductName NVARCHAR(255) NOT NULL,
    BasePrice DECIMAL(10,2),
    IsConfigurable BIT DEFAULT 1,
    CreatedDate DATETIME DEFAULT GETDATE()
);

CREATE TABLE ConfigurationOptions (
    OptionID INT PRIMARY KEY,
    ProductID INT FOREIGN KEY REFERENCES Products(ProductID),
    OptionName NVARCHAR(255) NOT NULL,
    OptionType VARCHAR(50), -- 'dropdown', 'slider', 'checkbox', etc.
    DefaultValue NVARCHAR(255),
    PriceModifier DECIMAL(10,2) DEFAULT 0,
    DisplayOrder INT,
    IsRequired BIT DEFAULT 0
);

CREATE TABLE ConfigurationSessions (
    SessionID UNIQUEIDENTIFIER PRIMARY KEY,
    ProductID INT FOREIGN KEY REFERENCES Products(ProductID),
    CustomerID NVARCHAR(100),
    ConfigurationData NVARCHAR(MAX), -- JSON data
    TotalPrice DECIMAL(10,2),
    Status VARCHAR(20) DEFAULT 'draft', -- 'draft', 'completed', 'quoted'
    CreatedDate DATETIME DEFAULT GETDATE(),
    LastModified DATETIME DEFAULT GETDATE()
);

Database integration questions

Which databases does Ignitionary support?

SQL Server, PostgreSQL, MySQL/MariaDB, and Oracle for relational stores, and MongoDB for document data — through native drivers or a REST data layer. Ignitionary reads from your existing tables and writes configuration records back on a schema you approve, with connections scoped to least-privilege credentials over TLS.

Do we have to migrate our data or adopt a new schema?

No. Ignitionary maps to your existing tables, column names, and relationships rather than importing everything into a proprietary model, so there's no migration project and your database stays the source of truth for product and pricing data.

Can we query configuration and quote history directly?

Yes — that's the point. Configurations, selected options, and quote outcomes are written as structured records in your database, so your team runs its own SQL, builds its own dashboards, and feeds its own warehouse without depending on a vendor report or CSV export.

Ready to Connect Your Database?

Leverage your existing data infrastructure with Ignitionary's flexible database integration