<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: API Consumption on Databricks in Community Articles</title>
    <link>https://community.databricks.com/t5/community-articles/api-consumption-on-databricks/m-p/138975#M779</link>
    <description>&lt;P&gt;Insightful and informative!&lt;/P&gt;</description>
    <pubDate>Thu, 13 Nov 2025 21:37:23 GMT</pubDate>
    <dc:creator>Brahmareddy</dc:creator>
    <dc:date>2025-11-13T21:37:23Z</dc:date>
    <item>
      <title>API Consumption on Databricks</title>
      <link>https://community.databricks.com/t5/community-articles/api-consumption-on-databricks/m-p/134487#M724</link>
      <description>&lt;P&gt;In this blog, I will be talking about the building the architecture to serve the API consumption on Databricks Platform. I will be using Lakebase approach for this. It will be useful for this kind of API requirement.&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;API Requirement:&lt;/U&gt;&lt;/STRONG&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Performance:&lt;/STRONG&gt;&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;Current Response Time&lt;STRONG&gt;:&lt;/STRONG&gt; 20–30 ms with average 14K calls/day.&lt;/LI&gt;&lt;LI&gt;Target Response Time (Future): Maintain &amp;lt;100 ms even at peak load of 70–80K calls/day with full roll-out.&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;&lt;STRONG&gt;Scalability:&lt;/STRONG&gt;&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;Must support a 4–5x increase in daily call volume&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;&lt;STRONG&gt;Availability:&lt;/STRONG&gt;&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;Maintain 99.9% uptime&lt;/LI&gt;&lt;LI&gt;Implement retry logic and circuit breakers for resilience&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;&lt;STRONG&gt;Security:&lt;/STRONG&gt;&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;Continue using OAuth 2.0 client credentials flow for consumers&lt;/LI&gt;&lt;LI&gt;Ensure APIM uses Managed Identity for backend access&lt;/LI&gt;&lt;LI&gt;Enforce IP restrictions and private endpoints&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;&lt;STRONG&gt;Monitoring &amp;amp; Observability:&lt;/STRONG&gt;&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;Track latency, error rates, and throughput via Azure Monitor / App Insights&lt;/LI&gt;&lt;LI&gt;Set up alerts for spikes or failures&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;There is an assumption that Data processing pipeline is already created to process the data either on NRT or through Batch Processing.&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="rathorer_0-1759990971452.png" style="width: 400px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/20592i798B47E1BBC08456/image-size/medium?v=v2&amp;amp;px=400" role="button" title="rathorer_0-1759990971452.png" alt="rathorer_0-1759990971452.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;This is kind of high-level flow assumed that Data platform would have all processing done based on NRT or Batch. This stage table could be gold table/ MV/ Live Table. API table is created to make sure that API does not hit to any of the base table and can reside in another Subnet as if required for Security policy. It can be directly populated from Silver layer itself and proper security by having the API specific user access on this table.&amp;nbsp;This Final API table would be having millions of records.&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;Process Flow:&lt;/U&gt;&lt;/STRONG&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;Final Delta API Table (Approx Million(s) records)&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ↓&lt;/P&gt;&lt;P&gt;Lakehouse Federation + Lakebase (Powered by Delta Caching + Photon + Materialized Views)&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ↓&lt;/P&gt;&lt;P&gt;APIM (OAuth2 + Managed Identity) → APIs (served via Lakebase endpoint)&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="rathorer_0-1760078458113.png" style="width: 400px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/20641i0EE03EB7CC07D837/image-size/medium?v=v2&amp;amp;px=400" role="button" title="rathorer_0-1760078458113.png" alt="rathorer_0-1760078458113.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="rathorer_1-1760078513459.png" style="width: 400px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/20642i1F467B8FE102413E/image-size/medium?v=v2&amp;amp;px=400" role="button" title="rathorer_1-1760078513459.png" alt="rathorer_1-1760078513459.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;H2&gt;&lt;STRONG&gt;A. Prereqs (one-time)&lt;/STRONG&gt;&lt;/H2&gt;&lt;OL&gt;&lt;LI&gt;&lt;STRONG&gt;Unity Catalog (UC):&lt;BR /&gt;&lt;/STRONG&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;UL&gt;&lt;LI&gt;Create a metastore, attach your workspace.&lt;/LI&gt;&lt;LI&gt;Set up external location for ADLS and storage credential.&lt;/LI&gt;&lt;LI&gt;Create catalogs: one for API table as current one is residing is separate subnet and another for all other Databricks processing.&lt;/LI&gt;&lt;/UL&gt;&lt;OL&gt;&lt;LI&gt;&lt;STRONG&gt;Networking (private only):&lt;BR /&gt;&lt;/STRONG&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;UL&gt;&lt;LI&gt;Private Endpoint to ADLS Gen2.&lt;/LI&gt;&lt;LI&gt;Private Link to Databricks workspace and Databricks SQL (Serverless) endpoints.&lt;/LI&gt;&lt;LI&gt;Keep VNET peering between Data VNET and Integration VNET (APIM).&lt;/LI&gt;&lt;LI&gt;Lock down egress with NSGs / UDRs if required.&lt;STRONG&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;/STRONG&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;OL&gt;&lt;LI&gt;&lt;STRONG&gt;Identity:&lt;BR /&gt;&lt;/STRONG&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;UL&gt;&lt;LI&gt;System-assigned Managed Identity on Azure Function/AKS and APIM.&lt;/LI&gt;&lt;LI&gt;Create Entra ID App (service principal) for Databricks SQL access or use MI → Entra ID → Databricks OBO (recommended).&lt;/LI&gt;&lt;LI&gt;In Databricks, create a user for that identity (SCIM) and grant least-privilege.&lt;/LI&gt;&lt;/UL&gt;&lt;OL&gt;&lt;LI&gt;&lt;STRONG&gt;Databricks SQL Warehouse (Serverless):&lt;BR /&gt;&lt;/STRONG&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;UL&gt;&lt;LI&gt;Photon: ON&lt;/LI&gt;&lt;LI&gt;Min/Max clusters: start 2–4 (autoscale), concurrency 20–50&lt;/LI&gt;&lt;LI&gt;Channel: Current&lt;/LI&gt;&lt;LI&gt;Spot: OK for dev, not for prod&lt;/LI&gt;&lt;LI&gt;Enable Serverless Result Cache (default)&lt;/LI&gt;&lt;/UL&gt;&lt;H2&gt;&lt;STRONG&gt;B. Lakehouse tables (Final Databricks table)&lt;/STRONG&gt;&lt;/H2&gt;&lt;P&gt;&lt;U&gt;Final (Gold) table should live in UC:&lt;/U&gt;&lt;/P&gt;&lt;P&gt;&lt;EM&gt;USE CATALOG gold;&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;USE SCHEMA api;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&lt;/EM&gt;&lt;/P&gt;&lt;P&gt;&lt;EM&gt;-- Create or Upgrade to a Delta table optimized for point lookups&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;CREATE TABLE IF NOT EXISTS customer_summary&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;(&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp; id STRING NOT NULL,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; -- primary lookup key for API&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp; customer_id STRING,&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp; cen_id STRING,&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp; churn_score DOUBLE,&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp; business_units ARRAY&amp;lt;STRING&amp;gt;,&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp; updated_at TIMESTAMP&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;)&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;USING DELTA&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;LOCATION 'abfss://&amp;lt;container&amp;gt;@&amp;lt;account&amp;gt;.dfs.core.windows.net/gold/api/customer_summary';&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&lt;/EM&gt;&lt;/P&gt;&lt;P&gt;&lt;EM&gt;-- Enable auto-optimization &amp;amp; liquid clustering&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;ALTER TABLE customer_summary SET TBLPROPERTIES (&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp; 'delta.autoOptimize.optimizeWrite' = 'true',&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp; 'delta.autoOptimize.autoCompact' = 'true',&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp; 'delta.feature.liquidClustering' = 'supported',&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp; 'delta.liquidClustering.autoMode.enabled' = 'true'&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;);&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&lt;/EM&gt;&lt;/P&gt;&lt;P&gt;&lt;EM&gt;-- Optional: Bloom filter index for high-selectivity key lookups&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;CREATE BLOOMFILTER INDEX bf_customer_summary_id&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;ON TABLE customer_summary&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;FOR COLUMNS(id) OPTIONS (fpp = 0.05, numItems = 30000000);&lt;/EM&gt;&lt;/P&gt;&lt;H2&gt;&lt;STRONG&gt;C. Connecting APIM/Function to Databricks SQL (Managed Identity, Private Link)&lt;/STRONG&gt;&lt;/H2&gt;&lt;H3&gt;&lt;STRONG&gt;1) APIM Policy (OAuth2 client credentials)&lt;/STRONG&gt;&lt;/H3&gt;&lt;P&gt;APIM continues to validate OAuth2 token from consumers (as you have now).&lt;BR /&gt;&amp;nbsp;Add &lt;STRONG&gt;retry + circuit breaker&lt;/STRONG&gt; at APIM:&lt;/P&gt;&lt;P&gt;&lt;EM&gt;&amp;lt;policies&amp;gt;&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp; &amp;lt;inbound&amp;gt;&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;base /&amp;gt;&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;validate-jwt header-name="Authorization" failed-validation-httpcode="401" require-scheme="Bearer"&amp;gt;&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;openid-config url="&lt;A href="https://login.microsoftonline.com/" target="_blank" rel="noopener"&gt;https://login.microsoftonline.com/&lt;/A&gt;&amp;lt;tenant-id&amp;gt;/v2.0/.well-known/openid-configuration" /&amp;gt;&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;audiences&amp;gt;&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;audience&amp;gt;api://your-api-app-id&amp;lt;/audience&amp;gt;&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/audiences&amp;gt;&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/validate-jwt&amp;gt;&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!-- Simple circuit breaker --&amp;gt;&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp; &amp;nbsp;&amp;lt;circuit-breaker id="cb-db" failure-ratio="0.5" sampling-duration="60" minimum-operations="20" break-duration="30" /&amp;gt;&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;retry condition="@(context.Response.StatusCode == 429 || context.Response.StatusCode &amp;gt;= 500)" count="2" interval="0.2" /&amp;gt;&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp; &amp;lt;/inbound&amp;gt;&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp; &amp;lt;backend&amp;gt;&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;base /&amp;gt;&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp; &amp;lt;/backend&amp;gt;&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp; &amp;lt;outbound&amp;gt;&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;base /&amp;gt;&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp; &amp;lt;/outbound&amp;gt;&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp; &amp;lt;on-error&amp;gt;&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;base /&amp;gt;&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp; &amp;lt;/on-error&amp;gt;&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;lt;/policies&amp;gt;&lt;BR /&gt;&lt;BR /&gt;&lt;/EM&gt;&lt;/P&gt;&lt;H3&gt;&lt;STRONG&gt;2) Azure Function (Python) → Databricks SQL with MSI&lt;/STRONG&gt;&lt;/H3&gt;&lt;P&gt;Use &lt;STRONG&gt;Managed Identity&lt;/STRONG&gt; to get an AAD token and connect with the &lt;STRONG&gt;databricks-sql-connector&lt;/STRONG&gt; (or ODBC) over &lt;STRONG&gt;Private Link&lt;/STRONG&gt; to the SQL Warehouse:&lt;/P&gt;&lt;P&gt;&lt;EM&gt;# requirements.txt&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;# azure-identity==1.15.0&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;# databricks-sql-connector==3.1.0&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;# tenacity==8.2.3&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&lt;/EM&gt;&lt;EM&gt;import os&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;from azure.identity import ManagedIdentityCredential&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;from databricks import sql&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;from tenacity import retry, stop_after_attempt, wait_exponential&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&lt;/EM&gt;&lt;EM&gt;DATABRICKS_SQL_ENDPOINT = os.environ["DBSQL_ENDPOINT"]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # e.g. adb-&amp;lt;id&amp;gt;&lt;BR /&gt;&amp;lt;region&amp;gt;.azuredatabricks.net&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;WAREHOUSE_ID&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = os.environ["DBSQL_WAREHOUSE_ID"]&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;CATALOG&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = "gold"&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;SCHEMA&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = "api"&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&lt;/EM&gt;&lt;EM&gt;# get AAD access token for Databricks&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;def aad_token():&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cred = ManagedIdentityCredential()&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; # scope for Databricks AAD&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; token = cred.get_token("2ff814a6-3304-4ab8-85cb-cd0e6f879c1d/.default")&amp;nbsp; # Databricks AAD resource ID&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return token.token&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=0.1, min=0.2, max=1))&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;def get_customer(customer_id:str):&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; with sql.connect(&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; server_hostname=DATABRICKS_SQL_ENDPOINT,&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; http_path=f"/sql/1.0/warehouses/{WAREHOUSE_ID}",&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; access_token=aad_token(),&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # AAD token from MSI&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _user_agent_entry="api-lakebase"&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ) as conn:&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; with conn.cursor() as cur:&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cur.execute(f"USE CATALOG {CATALOG}; USE SCHEMA {SCHEMA};")&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cur.execute(&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "SELECT id, customer_id, cen_id, churn_score, business_units, updated_at "&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "FROM customer_summary WHERE id = ? LIMIT 1",&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (customer_id,)&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; row = cur.fetchone()&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return None if row is None else dict(zip([c[0] for c in cur.description], row))&lt;/EM&gt;&lt;/P&gt;&lt;H1&gt;&lt;STRONG&gt;3) Meeting API SLOs&lt;/STRONG&gt;&lt;/H1&gt;&lt;H3&gt;&lt;STRONG&gt;Throughput math&lt;BR /&gt;&lt;/STRONG&gt;&lt;STRONG&gt;70–80K calls/day&lt;/STRONG&gt;&lt;SPAN&gt; = ~1 req/sec sustained, bursts ~5–20 req/sec.&lt;/SPAN&gt;&lt;/H3&gt;&lt;UL&gt;&lt;LI&gt;&lt;STRONG&gt;Serverless SQL + Photon&lt;/STRONG&gt; easily handles &lt;STRONG&gt;tens to hundreds of QPS&lt;/STRONG&gt; for point lookups on a well-clustered Delta table.&lt;BR /&gt;&lt;STRONG&gt;Latency (&amp;lt;100 ms target)&lt;/STRONG&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;UL&gt;&lt;LI&gt;&lt;STRONG&gt;Photon + liquid clustering + result cache&lt;/STRONG&gt; → 10–50 ms typical for single-row lookups.&lt;/LI&gt;&lt;LI&gt;Keep payloads small (project only needed columns).&lt;/LI&gt;&lt;LI&gt;Warm the result cache with a tiny “health” query every minute.&lt;/LI&gt;&lt;/UL&gt;&lt;H3&gt;&lt;STRONG&gt;Availability (99.9%)&lt;/STRONG&gt;&lt;/H3&gt;&lt;UL&gt;&lt;LI&gt;&lt;STRONG&gt;Serverless SQL Warehouses&lt;/STRONG&gt; provide high availability.&lt;/LI&gt;&lt;LI&gt;Add &lt;STRONG&gt;APIM retry + circuit breaker&lt;/STRONG&gt; (above) and &lt;STRONG&gt;Function retry&lt;/STRONG&gt; (Tenacity).&lt;/LI&gt;&lt;LI&gt;Provision &lt;STRONG&gt;min 2 clusters&lt;/STRONG&gt; for steady-state capacity; allow autoscale to 4–8.&lt;/LI&gt;&lt;/UL&gt;&lt;H1&gt;&lt;STRONG&gt;4) Performance &amp;amp; process improvements (the knobs)&lt;/STRONG&gt;&lt;/H1&gt;&lt;P&gt;&lt;STRONG&gt;Data layout&lt;/STRONG&gt;&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;STRONG&gt;Liquid Clustering (auto)&lt;/STRONG&gt; ON (you already chose this).&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;Small-file compaction:&lt;/STRONG&gt; nightly OPTIMIZE.&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;Bloom filter&lt;/STRONG&gt; on id (optional but helpful for point lookups).&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;Target file size:&lt;/STRONG&gt; 128–256 MB (Delta optimizer manages this with auto-compact).&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;&lt;STRONG&gt;Warehouse&lt;/STRONG&gt;&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;STRONG&gt;Photon: ON&lt;/STRONG&gt; (critical).&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;Serverless&lt;/STRONG&gt; preferred (lower cold-starts, managed).&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;Concurrency:&lt;/STRONG&gt; Start 20–50.&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;Autoscale:&lt;/STRONG&gt; min 2 / max 4 (raise if you see queueing).&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;Result cache:&lt;/STRONG&gt; default ON; don’t disable.&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;Channel:&lt;/STRONG&gt; Current.&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;Keep-alive pings&lt;/STRONG&gt; from Function every few minutes to reduce cold-starts.&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;&lt;STRONG&gt;Caching&lt;/STRONG&gt;&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;STRONG&gt;Delta cache&lt;/STRONG&gt; (on compute) helps when the same partitions hit frequently.&lt;/LI&gt;&lt;LI&gt;For strictly random single-key lookups, rely on Photon + metadata pruning + result cache.&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;&lt;STRONG&gt;Query design&lt;/STRONG&gt;&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;Use &lt;STRONG&gt;parameterized&lt;/STRONG&gt; SELECT … WHERE id = ? LIMIT 1.&lt;/LI&gt;&lt;LI&gt;**No SELECT ***. Project minimal columns.&lt;/LI&gt;&lt;LI&gt;Keep predicates SARGable (no function on the left side).&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;&lt;STRONG&gt;API level&lt;/STRONG&gt;&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;Tight &lt;STRONG&gt;timeouts&lt;/STRONG&gt; (e.g., 1–2 s) and &lt;STRONG&gt;retries&lt;/STRONG&gt; 2x with backoff.&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;Bulk endpoints&lt;/STRONG&gt; (optional): allow querying up to N ids per call to reduce chattiness.&lt;/LI&gt;&lt;/UL&gt;&lt;H1&gt;&lt;STRONG&gt;5) Security (Existing, pointing to Databricks)&lt;/STRONG&gt;&lt;/H1&gt;&lt;UL&gt;&lt;LI&gt;&lt;STRONG&gt;OAuth 2.0 client credentials&lt;/STRONG&gt; at APIM (unchanged).&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;Managed Identity&lt;/STRONG&gt; from APIM/Function to Databricks SQL (token exchange via Entra ID).&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;Private Endpoints&lt;/STRONG&gt; to:&lt;BR /&gt;&lt;UL&gt;&lt;LI&gt;ADLS Gen2&lt;/LI&gt;&lt;LI&gt;Databricks Workspace&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;Databricks SQL endpoint&lt;/STRONG&gt; (new)&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;IP restrictions&lt;/STRONG&gt; at APIM and Function subnets.&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;UC RBAC&lt;/STRONG&gt; on the gold.api.customer_summary table (least privilege).&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;No public ingress&lt;/STRONG&gt; to data plane.&lt;BR /&gt;&lt;BR /&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;H1&gt;&lt;STRONG&gt;6) Monitoring &amp;amp; observability&lt;/STRONG&gt;&lt;/H1&gt;&lt;P&gt;&lt;STRONG&gt;Azure side&lt;/STRONG&gt;&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;STRONG&gt;App Insights&lt;/STRONG&gt; on Function/AKS: track latency, p50/p95, error %, dependency calls to Databricks.&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;APIM Analytics:&lt;/STRONG&gt; backend latency, 4xx/5xx, throttle events.&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;Alerts:&lt;/STRONG&gt; 5xx spike, latency p95 &amp;gt; target, throttling &amp;gt; threshold.&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;&lt;STRONG&gt;Databricks side&lt;/STRONG&gt;&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;STRONG&gt;SQL Warehouse&lt;/STRONG&gt; → “Query history” &amp;amp; “Statement execution” metrics; set &lt;STRONG&gt;alerts&lt;/STRONG&gt; for queue time, duration.&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;System tables&lt;/STRONG&gt; (UC): system.query.history, system.access.audit.&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;Diagnostic settings&lt;/STRONG&gt; streaming to &lt;STRONG&gt;Log Analytics&lt;/STRONG&gt; (KQL dashboards).&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;&lt;STRONG&gt;KQL sketch (APIM)&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;&lt;EM&gt;AzureDiagnostics&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;| where ResourceType == "APIM"&lt;BR /&gt;&lt;/EM&gt;&lt;EM&gt;| summarize p50=percentile(DurationMs,50), p95=percentile(DurationMs,95), errors=countif(ResponseCode &amp;gt;= 500) by bin(TimeGenerated, 5m)&lt;/EM&gt;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Optimization Summary:&amp;nbsp;&lt;/STRONG&gt;&lt;/P&gt;&lt;TABLE width="429"&gt;&lt;TBODY&gt;&lt;TR&gt;&lt;TD width="205"&gt;&lt;P&gt;&lt;STRONG&gt;Optimization&lt;/STRONG&gt;&lt;/P&gt;&lt;/TD&gt;&lt;TD width="223"&gt;&lt;P&gt;&lt;STRONG&gt;Read Throughput (approx)&lt;/STRONG&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD width="205"&gt;&lt;P&gt;Photon + Delta Cache&lt;/P&gt;&lt;/TD&gt;&lt;TD width="223"&gt;&lt;P&gt;10,000+ QPS (primary key)&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD width="205"&gt;&lt;P&gt;Liquid Clustering Enabled&lt;/P&gt;&lt;/TD&gt;&lt;TD width="223"&gt;&lt;P&gt;Consistent &amp;lt;100ms response&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD width="205"&gt;&lt;P&gt;Materialized View + Cache&lt;/P&gt;&lt;P&gt;MV can be enabled only if the need of Aggregation and joins in API&lt;/P&gt;&lt;/TD&gt;&lt;TD width="223"&gt;&lt;P&gt;~5–30ms response&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Recommendations&amp;nbsp;Summary:&lt;/STRONG&gt;&lt;/P&gt;&lt;TABLE width="604"&gt;&lt;TBODY&gt;&lt;TR&gt;&lt;TD width="113"&gt;&lt;P&gt;&lt;STRONG&gt;Layer&lt;/STRONG&gt;&lt;/P&gt;&lt;/TD&gt;&lt;TD width="490"&gt;&lt;P&gt;&lt;STRONG&gt;Recommendation&lt;/STRONG&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD width="113"&gt;&lt;P&gt;Data Storage&lt;/P&gt;&lt;/TD&gt;&lt;TD width="490"&gt;&lt;P&gt;Delta Lake with Liquid Clustering (Auto mode)&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD width="113"&gt;&lt;P&gt;Query Engine&lt;/P&gt;&lt;/TD&gt;&lt;TD width="490"&gt;&lt;P&gt;Databricks Photon-enabled SQL Warehouse (Serverless preferred)&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD width="113"&gt;&lt;P&gt;Acceleration&lt;/P&gt;&lt;/TD&gt;&lt;TD width="490"&gt;&lt;P&gt;Delta Caching + Materialized Views&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD width="113"&gt;&lt;P&gt;Federation&lt;/P&gt;&lt;/TD&gt;&lt;TD width="490"&gt;&lt;P&gt;Expose via Lakebase&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD width="113"&gt;&lt;P&gt;API Layer&lt;/P&gt;&lt;/TD&gt;&lt;TD width="490"&gt;&lt;P&gt;Azure APIM + OAuth2 + Managed Identity&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD width="113"&gt;&lt;P&gt;Monitoring&lt;/P&gt;&lt;/TD&gt;&lt;TD width="490"&gt;&lt;P&gt;Azure Monitor + App Insights + Query History&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 10 Oct 2025 07:02:29 GMT</pubDate>
      <guid>https://community.databricks.com/t5/community-articles/api-consumption-on-databricks/m-p/134487#M724</guid>
      <dc:creator>rathorer</dc:creator>
      <dc:date>2025-10-10T07:02:29Z</dc:date>
    </item>
    <item>
      <title>Re: API Consumption on Databricks</title>
      <link>https://community.databricks.com/t5/community-articles/api-consumption-on-databricks/m-p/134987#M731</link>
      <description>&lt;P&gt;Sharp design choices, &lt;a href="https://community.databricks.com/t5/user/viewprofilepage/user-id/165156"&gt;@rathorer&lt;/a&gt;!&amp;nbsp;Appreciate you sharing this detailed architecture.&lt;/P&gt;</description>
      <pubDate>Wed, 15 Oct 2025 11:26:25 GMT</pubDate>
      <guid>https://community.databricks.com/t5/community-articles/api-consumption-on-databricks/m-p/134987#M731</guid>
      <dc:creator>Advika</dc:creator>
      <dc:date>2025-10-15T11:26:25Z</dc:date>
    </item>
    <item>
      <title>Re: API Consumption on Databricks</title>
      <link>https://community.databricks.com/t5/community-articles/api-consumption-on-databricks/m-p/134995#M732</link>
      <description>&lt;P&gt;Thanks&amp;nbsp;&lt;a href="https://community.databricks.com/t5/user/viewprofilepage/user-id/152834"&gt;@Advika&lt;/a&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 15 Oct 2025 12:25:45 GMT</pubDate>
      <guid>https://community.databricks.com/t5/community-articles/api-consumption-on-databricks/m-p/134995#M732</guid>
      <dc:creator>rathorer</dc:creator>
      <dc:date>2025-10-15T12:25:45Z</dc:date>
    </item>
    <item>
      <title>Re: API Consumption on Databricks</title>
      <link>https://community.databricks.com/t5/community-articles/api-consumption-on-databricks/m-p/138182#M771</link>
      <description>&lt;P&gt;Great post&amp;nbsp;&lt;a href="https://community.databricks.com/t5/user/viewprofilepage/user-id/165156"&gt;@rathorer&lt;/a&gt;&amp;nbsp;&lt;BR /&gt;&lt;BR /&gt;Can you explain your Lakebase implementation? I understand Lakebase is the Managed PostGres implementation for OLTP (from the Neon acquisition) but not clear the Photon with the Lakebase.&amp;nbsp;&lt;BR /&gt;&lt;BR /&gt;Thanks Venkat&lt;/P&gt;</description>
      <pubDate>Fri, 07 Nov 2025 20:58:00 GMT</pubDate>
      <guid>https://community.databricks.com/t5/community-articles/api-consumption-on-databricks/m-p/138182#M771</guid>
      <dc:creator>smithsonian</dc:creator>
      <dc:date>2025-11-07T20:58:00Z</dc:date>
    </item>
    <item>
      <title>Re: API Consumption on Databricks</title>
      <link>https://community.databricks.com/t5/community-articles/api-consumption-on-databricks/m-p/138923#M778</link>
      <description>&lt;P&gt;Insightful&amp;nbsp;&lt;a href="https://community.databricks.com/t5/user/viewprofilepage/user-id/165156"&gt;@rathorer&lt;/a&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 13 Nov 2025 12:54:59 GMT</pubDate>
      <guid>https://community.databricks.com/t5/community-articles/api-consumption-on-databricks/m-p/138923#M778</guid>
      <dc:creator>SurajW</dc:creator>
      <dc:date>2025-11-13T12:54:59Z</dc:date>
    </item>
    <item>
      <title>Re: API Consumption on Databricks</title>
      <link>https://community.databricks.com/t5/community-articles/api-consumption-on-databricks/m-p/138975#M779</link>
      <description>&lt;P&gt;Insightful and informative!&lt;/P&gt;</description>
      <pubDate>Thu, 13 Nov 2025 21:37:23 GMT</pubDate>
      <guid>https://community.databricks.com/t5/community-articles/api-consumption-on-databricks/m-p/138975#M779</guid>
      <dc:creator>Brahmareddy</dc:creator>
      <dc:date>2025-11-13T21:37:23Z</dc:date>
    </item>
  </channel>
</rss>

