{"allowedRenditionsWidth":["320","480","640","768","960","1200","1440","1920"],"canonicalLink":"https://www.snowflake.com/en/developers/guides/intro-to-online-feature-store-with-postgres-in-snowflake/","robotsTags":[],"templateName":"quickstart-page-template","language":"en","title":"Introduction to Online Feature Store with Postgres in Snowflake","cssClassNames":"page basicpage summit-page","analyticsPageType":"quickstart-page-template","analyticsCategory":"general","analyticsSubCategory":"","excludeFromAnalytics":false,"isPasswordProtected":false,"analyticsContentTags":["snowflake-site:taxonomy/solution-center/certification/quickstart","snowflake-site:taxonomy/product/ai","snowflake-site:taxonomy/product/applications-and-collaboration","snowflake-site:taxonomy/product/data-engineering"],"analyticsEnabled":true,"coveoConfig":{"pipeline":"snowflake.com","searchHub":"snowflake.com","organizationId":"snowflakecomputingproduction8neljofn","apiKey":"xx335921a6-2a0a-40f2-a167-e390b4766c3d"},"analyticsDebugMode":false,"analyticsData":{"excludeFromAnalytics":false,"subCategory":"","pageType":"quickstart-page-template","templateName":"quickstart-page-template","siteName":"snowflake","pageUrl":"/content/snowflake-site/global/en/developers/guides/intro-to-online-feature-store-with-postgres-in-snowflake","language":"en","category":"general","pageName":"Introduction to Online Feature Store with Postgres in Snowflake","contentTags":["snowflake-site:taxonomy/solution-center/certification/quickstart","snowflake-site:taxonomy/product/ai","snowflake-site:taxonomy/product/applications-and-collaboration","snowflake-site:taxonomy/product/data-engineering"]},":mappedPath":"/en/developers/guides/intro-to-online-feature-store-with-postgres-in-snowflake/",":type":"snowflake-site/components/structure/page","locale":"en",":path":"/content/snowflake-site/global/en/developers/guides/intro-to-online-feature-store-with-postgres-in-snowflake",":items":{"root":{"columnClassNames":{"markup_editor_1950346551":"aem-GridColumn aem-GridColumn--default--12","experiencefragment-banner":"aem-GridColumn aem-GridColumn--default--12","experiencefragment-header":"aem-GridColumn aem-GridColumn--default--12","responsivegrid":"aem-GridColumn aem-GridColumn--default--12","experiencefragment-footer":"aem-GridColumn aem-GridColumn--default--12","modal_container":"aem-GridColumn aem-GridColumn--default--12","markup_editor":"aem-GridColumn aem-GridColumn--default--12"},"gridClassNames":"aem-Grid aem-Grid--12 aem-Grid--default--12","columnCount":12,":items":{"experiencefragment-banner":{"id":"experiencefragment-f8097d5e75","localizedFragmentVariationPath":"/content/experience-fragments/snowflake-site/language-masters/en/site/pushdown-banner/master/jcr:content","configured":true,"xfModelPath":"/content/experience-fragments/snowflake-site/language-masters/en/site/pushdown-banner/master.xfmodel.json",":type":"snowflake-site/components/experiencefragment"},"experiencefragment-header":{"id":"experiencefragment-bda52fad2c","localizedFragmentVariationPath":"/content/experience-fragments/snowflake-site/language-masters/en/site/mega-nav-header/master/jcr:content","configured":true,"xfModelPath":"/content/experience-fragments/snowflake-site/language-masters/en/site/mega-nav-header/master.xfmodel.json","languageNavPath":"/content/snowflake-site/global/en/developers/guides/intro-to-online-feature-store-with-postgres-in-snowflake.languagenav.json",":type":"snowflake-site/components/experiencefragment"},"markup_editor_1950346551":{"id":"markup-editor-30927ca31a","title":" ","cssContent":".snowflake-markdown-table code[class*=language-],.snowflake-markdown-table code[class*=language-],.snowflake-markdown .snowflake-text code[class*=language-],.snowflake-markdown .snowflake-text pre[class*=language-]{background-color:rgba(var(--ui-12-rgb),.5);color:var(--text-01);text-shadow:none;padding:var(--spacing-00);border-radius:var(--spacing-00);font-size:smaller}","isGSAPEnabled":false,":type":"snowflake-site/components/markup-editor"},"responsivegrid":{"columnClassNames":{"quickstart_hero":"aem-GridColumn aem-GridColumn--default--12","flexible_column_cont":"aem-GridColumn aem-GridColumn--default--12","markup_editor":"aem-GridColumn aem-GridColumn--default--12"},"gridClassNames":"aem-Grid aem-Grid--12 aem-Grid--default--12","columnCount":12,":items":{"quickstart_hero":{"id":"quickstart-hero-c16c56f686","isDeveloperGuidesPage":false,"quickstartHeroFirstCertifiedTag":{"tagText":"Quickstart","tagColor":"#29B5E8","tagPath":"/content/cq:tags/snowflake-site/taxonomy/solution-center/certification/quickstart","tagIcon":""},"quickstartHeroTitle":{"lines":["Introduction to Online Feature Store with Postgres in Snowflake"],"type":"heading2",":type":"snowflake-site/components/title-v2"},"quickstartHeroAuthor":"Doris Lee, Dureti Shemsi","quickstartHeroFirstSnowflakeFeatureTag":{"tagText":"Model Development","tagColor":"#29B5E8","tagPath":"/content/cq:tags/snowflake-site/taxonomy/snowflake-feature/model-development","tagIcon":""},"quickstartHeroForkRepoLink":{"id":"button-e009ce3298","showOutboundIcon":false,"buttonLink":{"valid":true,"attributes":{"target":"_blank"},"url":"https://github.com/Snowflake-Labs/sfquickstarts/tree/master/site/sfguides/src/intro-to-online-feature-store-with-postgres-in-snowflake"},"linkTargetContentType":"GENERIC",":type":"snowflake-site/components/button","text":"Fork Repo","linkType":"SNOWFLAKE_EXTERNAL"},"quickstartHeroBreadcrumbs":[{"title":"Introduction to Online Feature Store with Postgres in Snowflake","url":"https://www.snowflake.com/content/snowflake-site/global/en/developers/guides/intro-to-online-feature-store-with-postgres-in-snowflake","currentPage":true},{"title":"Guides","url":"https://www.snowflake.com/content/snowflake-site/global/en/developers/guides","currentPage":false},{"title":"Snowflake for Developers","url":"https://www.snowflake.com/content/snowflake-site/global/en/developers","currentPage":false}],"fragmentPath":"/content/dam/snowflake-site/en/content-fragments/quickstarts/base-quickstart-cf",":type":"snowflake-site/components/quickstart/quickstart-hero"},"flexible_column_cont":{"id":"flexible-column-container-d7ea50eaab","propertiesId":"quickstart-template-main-flexible-container","type":"2-column-75-25","alignColumns":"top","containerMaxWidth":"extra-large","topPadding":"none","bottomPadding":"none","spaceBetween":"small","reverseOnMobile":false,"carouselOnMobile":false,"backgroundImageOption":"none","flexible_column_content_container_1":{"id":"container-3c09d90544","layout":"SIMPLE",":type":"snowflake-site/components/flexible-column-container/flexible-column-content-container",":items":{"contentfragment":{"id":"contentfragment-946fdf4fb1","paragraphs":["&lt;!-- ------------------------ --&gt;\n","\u003Ch2\u003EOverview\u003C/h2\u003E\n","\u003Cp\u003EThe Snowflake Online Feature Store with Postgres (Public Preview) provides low-letency feature retrieval for real-time ML inference. This guide demonstrates how to build a real-time fraud detection system using the Online Feature Store &mdash; covering online feature retrieval, time-windowed aggregations, streaming ingestion, and REST API usage.\u003C/p\u003E\n","\u003Cp\u003EYou'll learn how to register batch, aggregation, and stream Feature Views backed by a managed Postgres serving layer, and how to query and ingest data through the REST API endpoints.\u003C/p\u003E\n","\u003Cp\u003E\u003Cimg src=\"https://www.snowflake.com/content/dam/snowflake-site/developers/guides/intro-to-online-feature-store-with-postgres-in-snowflake/feature-store-architecture.png\" alt=\"Online Feature Store Architecture\"\u003E\u003C/p\u003E\n","\u003Ch3\u003EPrerequisites\u003C/h3\u003E\n\u003Cul\u003E\u003Cli\u003EA Snowflake account (non-trial) in AWS or Azure commercial regions\u003C/li\u003E\u003Cli\u003EBasic knowledge of Python and SQL\u003C/li\u003E\u003Cli\u003EFamiliarity with machine learning concepts\u003C/li\u003E\u003Cli\u003EACCOUNTADMIN access or equivalent permissions\u003C/li\u003E\u003Cli\u003E\u003Ccode\u003Esnowflake-ml-python\u003C/code\u003E version 1.41 or later\u003C/li\u003E\u003Cli\u003EA Programmatic Access Token (PAT) for authenticating to the Online Feature Store REST endpoints\u003C/li\u003E\u003C/ul\u003E\n","\u003Ch3\u003EWhat You'll Learn\u003C/h3\u003E\n\u003Cul\u003E\u003Cli\u003EHow to set up the Snowflake Feature Store with a Postgres-backed online service\u003C/li\u003E\u003Cli\u003EHow to register batch, aggregation, and stream Feature Views\u003C/li\u003E\u003Cli\u003EHow to query online features with low latency\u003C/li\u003E\u003Cli\u003EHow to define Stream and Real-time Feature Views\u003C/li\u003E\u003Cli\u003EHow to ingest streaming events and query features through the REST API\u003C/li\u003E\u003Cli\u003EHow to integrate with the Snowflake Model Registry\u003C/li\u003E\u003C/ul\u003E\n","\u003Ch3\u003EWhat You'll Need\u003C/h3\u003E\n\u003Cul\u003E\u003Cli\u003EA \u003Ca href=\"https://signup.snowflake.com/?utm_source=snowflake-devrel&amp;utm_medium=developer-guides&amp;utm_cta=developer-guides\"\u003ESnowflake\u003C/a\u003E account\u003C/li\u003E\u003Cli\u003EBasic understanding of Snowpark and Snowflake ML\u003C/li\u003E\u003Cli\u003EA Programmatic Access Token (PAT)\u003C/li\u003E\u003C/ul\u003E\n","\u003Ch3\u003EWhat You'll Build\u003C/h3\u003E\n\u003Cul\u003E\u003Cli\u003EA Feature Store with 3 online Feature Views (batch profile, tiled aggregation, stream velocity)\u003C/li\u003E\u003Cli\u003EReal-time fraud scoring with low lentency feature retrieval\u003C/li\u003E\u003Cli\u003EStream ingestion pipeline with 2-3 second end-to-end freshness\u003C/li\u003E\u003Cli\u003EREST API integration for feature query and stream ingest\u003C/li\u003E\u003C/ul\u003E\n&lt;!-- ------------------------ --&gt;\n","\u003Ch2\u003ESetup and Data Preparation\u003C/h2\u003E\n","\u003Cp\u003EThis section covers environment setup, creating the online service, and loading synthetic fraud data.\u003C/p\u003E\n","\u003Ch3\u003EDownload and Import the Notebook\u003C/h3\u003E\n\u003Col\u003E\u003Cli\u003EClick this link: \u003Ca href=\"assets/online_feature_store_fraud_detection.ipynb\"\u003Eonline_feature_store_fraud_detection.ipynb\u003C/a\u003E\u003C/li\u003E\u003Cli\u003EOn the GitHub page, click the \u003Cstrong\u003EDownload raw file\u003C/strong\u003E button (download icon in the top right of the file preview)\u003C/li\u003E\u003Cli\u003ESave the \u003Ccode\u003E.ipynb\u003C/code\u003E file to your computer\u003C/li\u003E\u003C/ol\u003E\n","\u003Cp\u003ENow import the notebook into Snowflake:\u003C/p\u003E\n\u003Col\u003E\u003Cli\u003ENavigate to \u003Cstrong\u003EProjects\u003C/strong\u003E &gt; \u003Cstrong\u003EWorkspaces\u003C/strong\u003E in Snowsight\u003C/li\u003E\u003Cli\u003EClick \u003Cstrong\u003E+ Add New\u003C/strong\u003E and choose \u003Cstrong\u003EUpload files\u003C/strong\u003E button\u003C/li\u003E\u003Cli\u003ESelect the downloaded \u003Ccode\u003Eonline_feature_store_fraud_detection.ipynb\u003C/code\u003E file from your computer\u003C/li\u003E\u003C/ol\u003E\n","\u003Ch3\u003ERun the Setup Cell\u003C/h3\u003E\n","\u003Cp\u003EThe notebook includes a \u003Cstrong\u003ESection 0: Setup\u003C/strong\u003E cell that creates all required resources:\u003C/p\u003E\n\u003Cul\u003E\u003Cli\u003EA dedicated role: \u003Ccode\u003EFS_DEMO_ROLE\u003C/code\u003E\u003C/li\u003E\u003Cli\u003EA warehouse: \u003Ccode\u003EFS_DEMO_WH\u003C/code\u003E\u003C/li\u003E\u003Cli\u003EA database: \u003Ccode\u003EFRAUD_OFS_DEMO_DB\u003C/code\u003E with schemas \u003Ccode\u003ESOURCE_DATA\u003C/code\u003E, \u003Ccode\u003EFEATURE_STORE\u003C/code\u003E, \u003Ccode\u003EML_PIPELINE\u003C/code\u003E\u003C/li\u003E\u003Cli\u003ENetwork rule and external access integration for the notebook\u003C/li\u003E\u003C/ul\u003E\n","\u003Cp\u003ERun this cell as \u003Ccode\u003EACCOUNTADMIN\u003C/code\u003E. You only need to run it once.\u003C/p\u003E\n","\u003Ch3\u003ESet Up Authentication (PAT)\u003C/h3\u003E\n","\u003Cp\u003EThe Postgres online service communicates via REST endpoints. Set your PAT as an environment variable in the notebook before reading online features:\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode class=\"language-python\"\u003Eimport os\nos.environ[&quot;SNOWFLAKE_PAT&quot;] = &quot;&lt;your_pat_token&gt;&quot;\n\u003C/code\u003E\u003C/pre\u003E\n","\u003Cp\u003ETo create a PAT in Snowsight: navigate to your profile menu &gt; \u003Cstrong\u003EMy profile\u003C/strong\u003E &gt; \u003Cstrong\u003ESettings\u003C/strong\u003E &gt; \u003Cstrong\u003EAuthentication\u003C/strong\u003E &gt; \u003Cstrong\u003EProgrammatic access tokens\u003C/strong\u003E &gt; \u003Cstrong\u003EGenerate new token\u003C/strong\u003E.\u003C/p\u003E\n&lt;!-- ------------------------ --&gt;\n","\u003Ch2\u003EInitialize Feature Store\u003C/h2\u003E\n","\u003Ch3\u003EInitialize Feature Store\u003C/h3\u003E\n","\u003Cp\u003EInitialize the Feature Store client, pointing it at the \u003Ccode\u003EFEATURE_STORE\u003C/code\u003E schema. This creates the internal metadata tables if they don't already exist.\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode class=\"language-python\"\u003Efrom snowflake.ml.feature_store import FeatureStore, CreationMode\n\nfs = FeatureStore(\n    session=session,\n    database=&quot;FRAUD_OFS_DEMO_DB&quot;,\n    name=&quot;FEATURE_STORE&quot;,\n    default_warehouse=&quot;FS_DEMO_WH&quot;,\n    creation_mode=CreationMode.CREATE_IF_NOT_EXIST,\n)\n\u003C/code\u003E\u003C/pre\u003E\n","\u003Ch3\u003ERegister Entity\u003C/h3\u003E\n","\u003Cp\u003EAn Entity defines the primary key used to join Feature Views together. Here we register a \u003Ccode\u003ECUSTOMER\u003C/code\u003E entity with \u003Ccode\u003ECUSTOMER_ID\u003C/code\u003E as the join key &mdash; all Feature Views in this guide will be keyed by customer.\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode class=\"language-python\"\u003Efrom snowflake.ml.feature_store import Entity\n\ncustomer_entity = Entity(\n    name=&quot;CUSTOMER&quot;,\n    join_keys=[&quot;CUSTOMER_ID&quot;],\n    desc=&quot;A customer identified by their unique customer ID&quot;,\n)\nfs.register_entity(customer_entity)\nfs.list_entities().show()\n\u003C/code\u003E\u003C/pre\u003E\n","\u003Ch2\u003ECreate Online Service\u003C/h2\u003E\n","\u003Cp\u003EThe online service is a managed Postgres serving layer. Create it once per Feature Store before registering feature views with online serving.\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode class=\"language-python\"\u003Eimport time\nfrom snowflake.ml.feature_store import online_service\n\ncreate_result = fs.create_online_service(\n    producer_role=&quot;FS_DEMO_ROLE&quot;,\n    consumer_role=&quot;FS_DEMO_ROLE&quot;,\n)\nprint(f&quot;Create result: {create_result}&quot;)\n\n# Wait for RUNNING status (takes several minutes on first creation)\nfor i in range(30):\n    status = fs.get_online_service_status()\n    if status.status == &quot;RUNNING&quot;:\n        break\n    print(f&quot;  [{i}] Status: {status.status}&quot;)\n    time.sleep(30)\n\nquery_url = online_service.endpoint_url(status, &quot;query&quot;)\ningest_url = online_service.endpoint_url(status, &quot;ingest&quot;)\nprint(f&quot;Query URL: {query_url}&quot;)\nprint(f&quot;Ingest URL: {ingest_url}&quot;)\n\u003C/code\u003E\u003C/pre\u003E\n&lt;!-- ------------------------ --&gt;\n","\u003Ch2\u003ERegister Feature Views\u003C/h2\u003E\n","\u003Cp\u003EThis section demonstrates three types of Feature Views &mdash; the core building blocks of the Online Feature Store.\u003C/p\u003E\n","\u003Ch3\u003EBatch Feature View: Customer Profile\u003C/h3\u003E\n","\u003Cp\u003EA batch feature view passes pre-computed features from an offline table to the online store. The online store serves the latest row per entity key.\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode class=\"language-python\"\u003Efrom snowflake.ml.feature_store import FeatureView, OnlineConfig, OnlineStoreType\n\nprofile_df = session.table(&quot;FRAUD_OFS_DEMO_DB.SOURCE_DATA.CUSTOMER_PROFILES&quot;)\n\nprofile_fv = FeatureView(\n    name=&quot;CUSTOMER_PROFILE_FEATURES&quot;,\n    entities=[customer_entity],\n    feature_df=profile_df,\n    timestamp_col=&quot;UPDATED_AT&quot;,\n    refresh_freq=&quot;1m&quot;,\n    online_config=OnlineConfig(\n        enable=True,\n        target_lag=&quot;10s&quot;,\n        store_type=OnlineStoreType.POSTGRES,\n    ),\n    desc=&quot;Customer profile features: account age, total transactions, avg amount&quot;,\n)\n\nregistered_profile_fv = fs.register_feature_view(profile_fv, &quot;V1&quot;, overwrite=True)\nprint(f&quot;Registered: {registered_profile_fv.name}/{registered_profile_fv.version}&quot;)\n\u003C/code\u003E\u003C/pre\u003E\n","\u003Ch3\u003ETime-Windowed Aggregation Feature View\u003C/h3\u003E\n","\u003Cp\u003EUse the \u003Ccode\u003EFeature\u003C/code\u003E class to define rolling-window aggregate features. The online service pre-computes partial aggregates (tiles) and merges them at query time.\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode class=\"language-python\"\u003Efrom snowflake.ml.feature_store import Feature\n\ntxn_features = [\n    Feature.sum(&quot;TRANSACTION_AMOUNT&quot;, &quot;1h&quot;).alias(&quot;SUM_AMT_1H&quot;),\n    Feature.sum(&quot;TRANSACTION_AMOUNT&quot;, &quot;24h&quot;).alias(&quot;SUM_AMT_24H&quot;),\n    Feature.count(&quot;TRANSACTION_AMOUNT&quot;, &quot;24h&quot;).alias(&quot;TXN_COUNT_24H&quot;),\n    Feature.avg(&quot;TRANSACTION_AMOUNT&quot;, &quot;7d&quot;).alias(&quot;AVG_AMT_7D&quot;),\n]\n\ntxn_df = session.table(&quot;FRAUD_OFS_DEMO_DB.SOURCE_DATA.TRANSACTIONS&quot;)\n\ntxn_agg_fv = FeatureView(\n    name=&quot;CUSTOMER_TXN_AGG&quot;,\n    entities=[customer_entity],\n    feature_df=txn_df,\n    features=txn_features,\n    timestamp_col=&quot;TRANSACTION_TS&quot;,\n    refresh_freq=&quot;1m&quot;,\n    feature_granularity=&quot;1 minute&quot;,\n    online_config=OnlineConfig(\n        enable=True,\n        store_type=OnlineStoreType.POSTGRES,\n    ),\n    desc=&quot;Rolling transaction aggregations: sum, count, avg over 1h/24h/7d windows&quot;,\n)\n\nregistered_txn_fv = fs.register_feature_view(txn_agg_fv, &quot;V1&quot;, overwrite=True)\nprint(f&quot;Registered: {registered_txn_fv.name}/{registered_txn_fv.version}&quot;)\n\u003C/code\u003E\u003C/pre\u003E\n","\u003Ch3\u003EStream Feature View: Transaction Velocity\u003C/h3\u003E\n","\u003Cp\u003EStream Feature Views ingest events in real time and serve updated features with 2-3 second end-to-end freshness.\u003C/p\u003E\n","\u003Ch4\u003ERegister a Stream Source\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode class=\"language-python\"\u003Efrom snowflake.ml.feature_store import StreamSource, StreamConfig\nfrom snowflake.snowpark.types import (\n    StructType, StructField, StringType, FloatType,\n    TimestampType, TimestampTimeZone,\n)\n\ntxn_stream = StreamSource(\n    name=&quot;TXN_EVENTS&quot;,\n    schema=StructType([\n        StructField(&quot;CUSTOMER_ID&quot;, StringType()),\n        StructField(&quot;TRANSACTION_TS&quot;, TimestampType(TimestampTimeZone.NTZ)),\n        StructField(&quot;TRANSACTION_AMOUNT&quot;, FloatType()),\n        StructField(&quot;MERCHANT_CATEGORY&quot;, StringType()),\n    ]),\n    desc=&quot;Real-time transaction events for velocity features&quot;,\n)\nfs.register_stream_source(txn_stream)\n\u003C/code\u003E\u003C/pre\u003E\n","\u003Ch4\u003EDefine Transformation and Register\u003C/h4\u003E\n","\u003Cp\u003EDefine a Python transformation function that runs on each ingested event. The \u003Ccode\u003Ebackfill_df\u003C/code\u003E provides historical data so the online store is pre-populated before any new events arrive.\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode class=\"language-python\"\u003Eimport pandas as pd\n\ndef compute_velocity(df: pd.DataFrame) -&gt; pd.DataFrame:\n    &quot;&quot;&quot;Flag high-velocity transactions.&quot;&quot;&quot;\n    df[&quot;IS_HIGH_AMOUNT&quot;] = (df[&quot;TRANSACTION_AMOUNT&quot;] &gt; 500).astype(int)\n    return df\n\nbackfill_df = session.table(&quot;FRAUD_OFS_DEMO_DB.SOURCE_DATA.TRANSACTIONS&quot;)\n\nstream_fv = FeatureView(\n    name=&quot;TXN_STREAM_VELOCITY&quot;,\n    entities=[customer_entity],\n    timestamp_col=&quot;TRANSACTION_TS&quot;,\n    stream_config=StreamConfig(\n        stream_source=txn_stream,\n        transformation_fn=compute_velocity,\n        backfill_df=backfill_df,\n    ),\n    online_config=OnlineConfig(\n        enable=True,\n        target_lag=&quot;10s&quot;,\n        store_type=OnlineStoreType.POSTGRES,\n    ),\n    desc=&quot;Stream-ingested transaction velocity: per-event features with 2-3s freshness&quot;,\n)\n\nregistered_stream_fv = fs.register_feature_view(stream_fv, &quot;V1&quot;, overwrite=True)\nprint(f&quot;Registered: {registered_stream_fv.name}/{registered_stream_fv.version}&quot;)\n\u003C/code\u003E\u003C/pre\u003E\n&lt;!-- ------------------------ --&gt;\n","\u003Ch2\u003EOnline Feature Retrieval\u003C/h2\u003E\n","\u003Ch3\u003ERead Features from the Online Store\u003C/h3\u003E\n","\u003Cp\u003ERetrieve feature values by entity key with low latency:\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode class=\"language-python\"\u003Efv = fs.get_feature_view(&quot;CUSTOMER_PROFILE_FEATURES&quot;, &quot;V1&quot;)\n\nonline_df = fs.read_feature_view(\n    fv,\n    keys=[[&quot;CUST_000001&quot;], [&quot;CUST_000042&quot;]],\n    store_type=&quot;online&quot;,\n)\nonline_df.show()\n\u003C/code\u003E\u003C/pre\u003E\n","\u003Ch3\u003ERead Multiple Feature Views\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode class=\"language-python\"\u003Etxn_fv = fs.get_feature_view(&quot;CUSTOMER_TXN_AGG&quot;, &quot;V1&quot;)\n\ntxn_online = fs.read_feature_view(\n    txn_fv,\n    keys=[[&quot;CUST_000001&quot;]],\n    store_type=&quot;online&quot;,\n)\ntxn_online.show()\n\u003C/code\u003E\u003C/pre\u003E\n","\u003Ch3\u003ELatency Expectations\u003C/h3\u003E\n","\u003Cp\u003EThe Postgres online store achieves:\u003C/p\u003E\n\u003Cul\u003E\u003Cli\u003E\u003Cstrong\u003Ep50\u003C/strong\u003E: sub-10ms\u003C/li\u003E\u003Cli\u003E\u003Cstrong\u003Ep95\u003C/strong\u003E: sub-15ms\u003C/li\u003E\u003Cli\u003E\u003Cstrong\u003Ep99\u003C/strong\u003E: sub-20ms\u003C/li\u003E\u003C/ul\u003E\n","\u003Cp\u003EFor benchmarking in your own environment, see the \u003Ca href=\"https://github.com/Snowflake-Labs/snowflake-feature-store-online-benchmark-kit\"\u003EOnline Feature Store Benchmark Kit\u003C/a\u003E.\u003C/p\u003E\n&lt;!-- ------------------------ --&gt;\n","\u003Ch2\u003EStream Ingestion\u003C/h2\u003E\n","\u003Ch3\u003EIngest Events via Python SDK\u003C/h3\u003E\n","\u003Cp\u003EUse \u003Ccode\u003Efs.stream_ingest()\u003C/code\u003E to push events in real time. Ingested events are available in the online store within 2-3 seconds.\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode class=\"language-python\"\u003Eimport time\nfrom datetime import datetime\n\n# Ingest a new transaction event\nfs.stream_ingest(\n    stream_source=&quot;TXN_EVENTS&quot;,\n    records=[\n        {\n            &quot;CUSTOMER_ID&quot;: &quot;CUST_000042&quot;,\n            &quot;TRANSACTION_TS&quot;: datetime.now().strftime(&quot;%Y-%m-%d %H:%M:%S&quot;),\n            &quot;TRANSACTION_AMOUNT&quot;: 2500.00,\n            &quot;MERCHANT_CATEGORY&quot;: &quot;electronics&quot;,\n        }\n    ],\n)\nprint(&quot;Event ingested. Waiting for online store to update...&quot;)\ntime.sleep(3)\n\n# Verify the update\nstream_fv = fs.get_feature_view(&quot;TXN_STREAM_VELOCITY&quot;, &quot;V1&quot;)\nresult = fs.read_feature_view(\n    stream_fv,\n    keys=[[&quot;CUST_000042&quot;]],\n    store_type=&quot;online&quot;,\n)\nresult.show()\n\u003C/code\u003E\u003C/pre\u003E\n","\u003Ch3\u003EBefore/After Comparison\u003C/h3\u003E\n","\u003Cp\u003EThis demonstrates the end-to-end freshness of stream ingestion. We read the feature value before ingesting a new event, wait 3 seconds, then read again. You should see \u003Ccode\u003EIS_HIGH_AMOUNT\u003C/code\u003E flip to \u003Ccode\u003E1\u003C/code\u003E after the high-value transaction is ingested &mdash; confirming that the online store updates within seconds.\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode class=\"language-python\"\u003E# Read before ingest\nbefore = fs.read_feature_view(stream_fv, keys=[[&quot;CUST_000042&quot;]], store_type=&quot;online&quot;)\nprint(&quot;BEFORE:&quot;, before.to_pandas().to_string(index=False))\n\n# Ingest suspicious transaction\nfs.stream_ingest(&quot;TXN_EVENTS&quot;, records=[{\n    &quot;CUSTOMER_ID&quot;: &quot;CUST_000042&quot;,\n    &quot;TRANSACTION_TS&quot;: datetime.now().strftime(&quot;%Y-%m-%d %H:%M:%S&quot;),\n    &quot;TRANSACTION_AMOUNT&quot;: 5000.00,\n    &quot;MERCHANT_CATEGORY&quot;: &quot;crypto_exchange&quot;,\n}])\ntime.sleep(3)\n\n# Read after ingest\nafter = fs.read_feature_view(stream_fv, keys=[[&quot;CUST_000042&quot;]], store_type=&quot;online&quot;)\nprint(&quot;AFTER:&quot;, after.to_pandas().to_string(index=False))\n\u003C/code\u003E\u003C/pre\u003E\n&lt;!-- ------------------------ --&gt;\n","\u003Ch2\u003EREST API: Query and Ingest\u003C/h2\u003E\n","\u003Cp\u003EThe online service exposes HTTP endpoints for feature retrieval and stream ingestion. These can be called from any client (Python, curl, application code).\u003C/p\u003E\n","\u003Ch3\u003EGet Endpoint URLs\u003C/h3\u003E\n","\u003Cp\u003EIn Python, retrieve the URLs from the online service status:\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode class=\"language-python\"\u003Efrom snowflake.ml.feature_store import online_service\n\nstatus = fs.get_online_service_status()\nquery_url = online_service.endpoint_url(status, &quot;query&quot;)\ningest_url = online_service.endpoint_url(status, &quot;ingest&quot;)\n\nprint(f&quot;Query: {query_url}&quot;)\nprint(f&quot;Ingest: {ingest_url}&quot;)\n\u003C/code\u003E\u003C/pre\u003E\n","\u003Ch3\u003EQuery Endpoint\u003C/h3\u003E\n","\u003Cp\u003ERetrieve features via the REST query API:\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode class=\"language-bash\"\u003Eexport SNOWFLAKE_PAT=&quot;&lt;your_pat_token&gt;&quot;\nexport QUERY_URL=&quot;&lt;query_endpoint_url&gt;&quot;\n\ncurl -s -X POST &quot;$QUERY_URL/api/v1/query&quot; \\\n  -H &quot;Authorization: Snowflake Token=\\&quot;$SNOWFLAKE_PAT\\&quot;&quot; \\\n  -H &quot;Content-Type: application/json&quot; \\\n  -d '{\n    &quot;feature_view&quot;: &quot;CUSTOMER_TXN_AGG&quot;,\n    &quot;version&quot;: &quot;V1&quot;,\n    &quot;keys&quot;: [[&quot;CUST_000001&quot;], [&quot;CUST_000042&quot;]]\n  }'\n\u003C/code\u003E\u003C/pre\u003E\n","\u003Ch3\u003EIngest Endpoint\u003C/h3\u003E\n","\u003Cp\u003EPush events via the REST ingest API:\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode class=\"language-bash\"\u003Eexport INGEST_URL=&quot;&lt;ingest_endpoint_url&gt;&quot;\n\ncurl -s -X POST &quot;$INGEST_URL/api/v1/ingest&quot; \\\n  -H &quot;Authorization: Snowflake Token=\\&quot;$SNOWFLAKE_PAT\\&quot;&quot; \\\n  -H &quot;Content-Type: application/json&quot; \\\n  -d '{\n    &quot;stream_source&quot;: &quot;TXN_EVENTS&quot;,\n    &quot;records&quot;: [\n      {\n        &quot;CUSTOMER_ID&quot;: &quot;CUST_000042&quot;,\n        &quot;TRANSACTION_TS&quot;: &quot;2026-07-30 10:15:00&quot;,\n        &quot;TRANSACTION_AMOUNT&quot;: 3200.00,\n        &quot;MERCHANT_CATEGORY&quot;: &quot;jewelry&quot;\n      }\n    ]\n  }'\n\u003C/code\u003E\u003C/pre\u003E\n&lt;!-- ------------------------ --&gt;\n","\u003Ch2\u003EModel Registry Integration\u003C/h2\u003E\n","\u003Cp\u003EThe Online Feature Store integrates with the Snowflake Model Registry. When deploying a model as a service, you can configure automatic feature retrieval so the inference endpoint only needs entity IDs.\u003C/p\u003E\n\u003Cblockquote\u003E\n","\u003Cp\u003ENOTE:\nModel training is handled in the notebook. The notebook uses \u003Ccode\u003Efs.generate_training_set()\u003C/code\u003E to create a point-in-time correct training dataset from the Feature Views above, then trains an XGBoost fraud classifier. See the notebook for full training details.\u003C/p\u003E\n\u003C/blockquote\u003E\n","\u003Ch3\u003ELog Model to Registry\u003C/h3\u003E\n","\u003Cp\u003EAfter training in the notebook, the model is registered:\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode class=\"language-python\"\u003Efrom snowflake.ml.registry import Registry\n\nregistry = Registry(session=session)\n\nmv = registry.log_model(\n    model=trained_model,\n    model_name=&quot;FRAUD_DETECTION_MODEL&quot;,\n    version_name=&quot;V1&quot;,\n    metrics={&quot;auc&quot;: auc_score, &quot;f1&quot;: f1_score},\n)\n\u003C/code\u003E\u003C/pre\u003E\n","\u003Ch3\u003EDeploy with Automatic Feature Retrieval\u003C/h3\u003E\n","\u003Cp\u003EPass \u003Ccode\u003Efeature_sources_per_function\u003C/code\u003E to have the service automatically look up features from the online store at inference time. You only need to send the entity ID (\u003Ccode\u003ECUSTOMER_ID\u003C/code\u003E) in the request.\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode class=\"language-python\"\u003Emv.create_service(\n    service_name=&quot;FRAUD_SCORING_SVC&quot;,\n    service_compute_pool=&quot;ML_INFERENCE_POOL&quot;,\n    ingress_enabled=True,\n    feature_sources_per_function={\n        &quot;predict&quot;: [registered_profile_fv, registered_txn_fv],\n    },\n)\n\u003C/code\u003E\u003C/pre\u003E\n","\u003Cp\u003EWith this configuration, a prediction request only needs:\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode class=\"language-json\"\u003E{&quot;CUSTOMER_ID&quot;: &quot;CUST_000042&quot;}\n\u003C/code\u003E\u003C/pre\u003E\n","\u003Cp\u003EThe service fetches \u003Ccode\u003ECUSTOMER_PROFILE_FEATURES\u003C/code\u003E and \u003Ccode\u003ECUSTOMER_TXN_AGG\u003C/code\u003E from the online store automatically before invoking the model.\u003C/p\u003E\n&lt;!-- ------------------------ --&gt;\n","\u003Ch2\u003EClean Up\u003C/h2\u003E\n","\u003Ch3\u003EDrop the Online Service\u003C/h3\u003E\n","\u003Cp\u003EThe Postgres online service runs continuously. Drop it from the notebook when done:\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode class=\"language-python\"\u003Efs.drop_online_service()\n\u003C/code\u003E\u003C/pre\u003E\n","\u003Ch3\u003ERun the Teardown Script\u003C/h3\u003E\n\u003Col\u003E\u003Cli\u003EOpen Snowflake and navigate to \u003Cstrong\u003EProjects\u003C/strong\u003E &gt; \u003Cstrong\u003EWorkspaces\u003C/strong\u003E\u003C/li\u003E\u003Cli\u003ECreate a new SQL file and paste the following:\u003C/li\u003E\u003C/ol\u003E\n\u003Cpre\u003E\u003Ccode class=\"language-sql\"\u003EUSE ROLE ACCOUNTADMIN;\n\nSET USERNAME = (SELECT CURRENT_USER());\n\n-- Drop online service resources (handled by fs.drop_online_service() above)\n-- Drop database (drops all schemas, tables, feature views, dynamic tables)\nUSE ROLE FS_DEMO_ROLE;\nDROP DATABASE IF EXISTS FRAUD_OFS_DEMO_DB;\nDROP WAREHOUSE IF EXISTS FS_DEMO_WH;\nDROP COMPUTE POOL IF EXISTS FS_DEMO_INFERENCE_POOL;\n\n-- Drop integration and role\nUSE ROLE ACCOUNTADMIN;\nDROP INTEGRATION IF EXISTS FRAUD_OFS_DEMO_ALLOW_ALL_INTEGRATION;\n\nREVOKE CREATE DATABASE ON ACCOUNT FROM ROLE FS_DEMO_ROLE;\nREVOKE CREATE WAREHOUSE ON ACCOUNT FROM ROLE FS_DEMO_ROLE;\nREVOKE CREATE COMPUTE POOL ON ACCOUNT FROM ROLE FS_DEMO_ROLE;\nREVOKE BIND SERVICE ENDPOINT ON ACCOUNT FROM ROLE FS_DEMO_ROLE;\nREVOKE IMPORT SHARE ON ACCOUNT FROM ROLE FS_DEMO_ROLE;\nREVOKE EXECUTE TASK ON ACCOUNT FROM ROLE FS_DEMO_ROLE;\nREVOKE EXECUTE MANAGED TASK ON ACCOUNT FROM ROLE FS_DEMO_ROLE;\n\nREVOKE ROLE FS_DEMO_ROLE FROM USER identifier($USERNAME);\nDROP ROLE IF EXISTS FS_DEMO_ROLE;\n\nSELECT 'Teardown complete.' AS STATUS;\n\u003C/code\u003E\u003C/pre\u003E\n&lt;!-- ------------------------ --&gt;\n","\u003Ch2\u003EConclusion and Resources\u003C/h2\u003E\n","\u003Cp\u003ECongratulations! You've built a real-time fraud detection system using the Snowflake Online Feature Store with Postgres.\u003C/p\u003E\n","\u003Ch3\u003EWhat You Learned\u003C/h3\u003E\n\u003Cul\u003E\u003Cli\u003EHow to create a Postgres-backed online service with \u003Ccode\u003Ecreate_online_service()\u003C/code\u003E\u003C/li\u003E\u003Cli\u003EHow to register batch, aggregation, and stream Feature Views with \u003Ccode\u003EOnlineStoreType.POSTGRES\u003C/code\u003E\u003C/li\u003E\u003Cli\u003EHow to retrieve online features with low latency\u003C/li\u003E\u003Cli\u003EHow to ingest streaming events with 2-3 second end-to-end freshness\u003C/li\u003E\u003Cli\u003EHow to use the REST API endpoints for feature query and stream ingest\u003C/li\u003E\u003Cli\u003EHow to integrate with Model Registry for automatic feature retrieval at inference time\u003C/li\u003E\u003C/ul\u003E\n","\u003Ch3\u003EKey Takeaways\u003C/h3\u003E\n\u003Cul\u003E\u003Cli\u003E\u003Cstrong\u003EPostgres Online Store\u003C/strong\u003E delivers p50 ~5-10ms in-region latency via the REST query API\u003C/li\u003E\u003Cli\u003E\u003Cstrong\u003ETime-windowed aggregations\u003C/strong\u003E (\u003Ccode\u003EFeature.sum/count/avg\u003C/code\u003E) compute rolling metrics automatically\u003C/li\u003E\u003Cli\u003E\u003Cstrong\u003EStream Feature Views\u003C/strong\u003E provide 2-3 second freshness via REST ingest\u003C/li\u003E\u003Cli\u003E\u003Cstrong\u003EREST API\u003C/strong\u003E enables language-agnostic integration (curl, Python, any HTTP client)\u003C/li\u003E\u003Cli\u003E\u003Cstrong\u003E\u003Ccode\u003Efeature_sources_per_function\u003C/code\u003E\u003C/strong\u003E eliminates the need for clients to fetch features manually\u003C/li\u003E\u003C/ul\u003E\n","\u003Ch3\u003ERelated Resources\u003C/h3\u003E\n\u003Cul\u003E\u003Cli\u003E\u003Ca href=\"https://docs.snowflake.com/en/developer-guide/snowflake-ml/feature-store/online-feature-store\"\u003EServing Online Features (Postgres)\u003C/a\u003E\u003C/li\u003E\u003Cli\u003E\u003Ca href=\"assets/online_feature_store_fraud_detection.ipynb\"\u003EOnline Feature Store Quickstart Notebook\u003C/a\u003E\u003C/li\u003E\u003Cli\u003E\u003Ca href=\"https://docs.snowflake.com/en/developer-guide/snowflake-ml/feature-store/overview\"\u003ESnowflake Feature Store Documentation\u003C/a\u003E\u003C/li\u003E\u003Cli\u003E\u003Ca href=\"https://docs.snowflake.com/developer-guide/snowflake-ml/feature-store/online-feature-store-ingest-api-reference\"\u003EIngest API Reference\u003C/a\u003E\u003C/li\u003E\u003Cli\u003E\u003Ca href=\"https://docs.snowflake.com/developer-guide/snowflake-ml/feature-store/online-feature-store-query-api-reference\"\u003EQuery API Reference\u003C/a\u003E\u003C/li\u003E\u003Cli\u003E\u003Ca href=\"https://github.com/Snowflake-Labs/snowflake-feature-store-online-benchmark-kit\"\u003EOnline Feature Store Benchmark Kit\u003C/a\u003E\u003C/li\u003E\u003Cli\u003E\u003Ca href=\"https://docs.snowflake.com/developer-guide/snowflake-ml/inference/real-time-inference-rest-api#label-real-time-inference-online-feature-store-integration\"\u003EReal-time Inference with Online Feature Store\u003C/a\u003E\u003C/li\u003E\u003Cli\u003E\u003Ca href=\"https://docs.snowflake.com/developer-guide/snowflake-ml/feature-store/advanced-feature-engineering\"\u003EAdvanced Feature Engineering (Aggregations)\u003C/a\u003E\u003C/li\u003E\u003Cli\u003E\u003Ca href=\"https://docs.snowflake.com/user-guide/programmatic-access-tokens\"\u003EProgrammatic Access Tokens\u003C/a\u003E\u003C/li\u003E\u003C/ul\u003E\n","\u003Ch3\u003ENext Steps\u003C/h3\u003E\n\u003Cul\u003E\u003Cli\u003ETry the feature store with your own datasets\u003C/li\u003E\u003Cli\u003EIntegrate online features into production applications via the REST query API\u003C/li\u003E\u003C/ul\u003E"],"description":"","title":"Introduction to Online Feature Store with Postgres in Snowflake","isDeveloperGuidesPage":false,":type":"snowflake-site/components/contentfragment","model":"snowflake-site/models/quickstart-article",":items":{},":itemsOrder":[],"elements":{"quickstartArticleBody":{"dataType":"string","value":"\u003C!-- ------------------------ --\u003E\n## Overview\n\nThe Snowflake Online Feature Store with Postgres (Public Preview) provides low-letency feature retrieval for real-time ML inference. This guide demonstrates how to build a real-time fraud detection system using the Online Feature Store — covering online feature retrieval, time-windowed aggregations, streaming ingestion, and REST API usage.\n\nYou'll learn how to register batch, aggregation, and stream Feature Views backed by a managed Postgres serving layer, and how to query and ingest data through the REST API endpoints.\n\n![Online Feature Store Architecture](https://www.snowflake.com/content/dam/snowflake-site/developers/guides/intro-to-online-feature-store-with-postgres-in-snowflake/feature-store-architecture.png)\n\n### Prerequisites\n- A Snowflake account (non-trial) in AWS or Azure commercial regions\n- Basic knowledge of Python and SQL\n- Familiarity with machine learning concepts\n- ACCOUNTADMIN access or equivalent permissions\n- `snowflake-ml-python` version 1.41 or later\n- A Programmatic Access Token (PAT) for authenticating to the Online Feature Store REST endpoints\n\n### What You'll Learn\n- How to set up the Snowflake Feature Store with a Postgres-backed online service\n- How to register batch, aggregation, and stream Feature Views\n- How to query online features with low latency\n- How to define Stream and Real-time Feature Views\n- How to ingest streaming events and query features through the REST API\n- How to integrate with the Snowflake Model Registry\n\n### What You'll Need\n- A [Snowflake](https://signup.snowflake.com/?utm_source=snowflake-devrel&utm_medium=developer-guides&utm_cta=developer-guides) account\n- Basic understanding of Snowpark and Snowflake ML\n- A Programmatic Access Token (PAT)\n\n### What You'll Build\n- A Feature Store with 3 online Feature Views (batch profile, tiled aggregation, stream velocity)\n- Real-time fraud scoring with low lentency feature retrieval\n- Stream ingestion pipeline with 2-3 second end-to-end freshness\n- REST API integration for feature query and stream ingest\n\n\u003C!-- ------------------------ --\u003E\n## Setup and Data Preparation\n\nThis section covers environment setup, creating the online service, and loading synthetic fraud data.\n\n### Download and Import the Notebook\n\n1. Click this link: [online_feature_store_fraud_detection.ipynb](assets/online_feature_store_fraud_detection.ipynb)\n2. On the GitHub page, click the **Download raw file** button (download icon in the top right of the file preview)\n3. Save the `.ipynb` file to your computer\n\nNow import the notebook into Snowflake:\n\n1. Navigate to **Projects** \u003E **Workspaces** in Snowsight\n2. Click **+ Add New** and choose **Upload files** button\n3. Select the downloaded `online_feature_store_fraud_detection.ipynb` file from your computer\n\n\n### Run the Setup Cell\n\nThe notebook includes a **Section 0: Setup** cell that creates all required resources:\n- A dedicated role: `FS_DEMO_ROLE`\n- A warehouse: `FS_DEMO_WH`\n- A database: `FRAUD_OFS_DEMO_DB` with schemas `SOURCE_DATA`, `FEATURE_STORE`, `ML_PIPELINE`\n- Network rule and external access integration for the notebook\n\nRun this cell as `ACCOUNTADMIN`. You only need to run it once.\n\n\n\n### Set Up Authentication (PAT)\n\nThe Postgres online service communicates via REST endpoints. Set your PAT as an environment variable in the notebook before reading online features:\n\n```python\nimport os\nos.environ[\"SNOWFLAKE_PAT\"] = \"\u003Cyour_pat_token\u003E\"\n```\n\nTo create a PAT in Snowsight: navigate to your profile menu \u003E **My profile** \u003E **Settings** \u003E **Authentication** \u003E **Programmatic access tokens** \u003E **Generate new token**.\n\n\u003C!-- ------------------------ --\u003E\n## Initialize Feature Store\n\n### Initialize Feature Store\n\nInitialize the Feature Store client, pointing it at the `FEATURE_STORE` schema. This creates the internal metadata tables if they don't already exist.\n\n```python\nfrom snowflake.ml.feature_store import FeatureStore, CreationMode\n\nfs = FeatureStore(\n    session=session,\n    database=\"FRAUD_OFS_DEMO_DB\",\n    name=\"FEATURE_STORE\",\n    default_warehouse=\"FS_DEMO_WH\",\n    creation_mode=CreationMode.CREATE_IF_NOT_EXIST,\n)\n```\n\n### Register Entity\n\nAn Entity defines the primary key used to join Feature Views together. Here we register a `CUSTOMER` entity with `CUSTOMER_ID` as the join key — all Feature Views in this guide will be keyed by customer.\n\n```python\nfrom snowflake.ml.feature_store import Entity\n\ncustomer_entity = Entity(\n    name=\"CUSTOMER\",\n    join_keys=[\"CUSTOMER_ID\"],\n    desc=\"A customer identified by their unique customer ID\",\n)\nfs.register_entity(customer_entity)\nfs.list_entities().show()\n```\n\n## Create Online Service\n\nThe online service is a managed Postgres serving layer. Create it once per Feature Store before registering feature views with online serving.\n\n```python\nimport time\nfrom snowflake.ml.feature_store import online_service\n\ncreate_result = fs.create_online_service(\n    producer_role=\"FS_DEMO_ROLE\",\n    consumer_role=\"FS_DEMO_ROLE\",\n)\nprint(f\"Create result: {create_result}\")\n\n# Wait for RUNNING status (takes several minutes on first creation)\nfor i in range(30):\n    status = fs.get_online_service_status()\n    if status.status == \"RUNNING\":\n        break\n    print(f\"  [{i}] Status: {status.status}\")\n    time.sleep(30)\n\nquery_url = online_service.endpoint_url(status, \"query\")\ningest_url = online_service.endpoint_url(status, \"ingest\")\nprint(f\"Query URL: {query_url}\")\nprint(f\"Ingest URL: {ingest_url}\")\n```\n\n\n\u003C!-- ------------------------ --\u003E\n## Register Feature Views\n\nThis section demonstrates three types of Feature Views — the core building blocks of the Online Feature Store.\n\n### Batch Feature View: Customer Profile\n\nA batch feature view passes pre-computed features from an offline table to the online store. The online store serves the latest row per entity key.\n\n```python\nfrom snowflake.ml.feature_store import FeatureView, OnlineConfig, OnlineStoreType\n\nprofile_df = session.table(\"FRAUD_OFS_DEMO_DB.SOURCE_DATA.CUSTOMER_PROFILES\")\n\nprofile_fv = FeatureView(\n    name=\"CUSTOMER_PROFILE_FEATURES\",\n    entities=[customer_entity],\n    feature_df=profile_df,\n    timestamp_col=\"UPDATED_AT\",\n    refresh_freq=\"1m\",\n    online_config=OnlineConfig(\n        enable=True,\n        target_lag=\"10s\",\n        store_type=OnlineStoreType.POSTGRES,\n    ),\n    desc=\"Customer profile features: account age, total transactions, avg amount\",\n)\n\nregistered_profile_fv = fs.register_feature_view(profile_fv, \"V1\", overwrite=True)\nprint(f\"Registered: {registered_profile_fv.name}/{registered_profile_fv.version}\")\n```\n\n### Time-Windowed Aggregation Feature View\n\nUse the `Feature` class to define rolling-window aggregate features. The online service pre-computes partial aggregates (tiles) and merges them at query time.\n\n```python\nfrom snowflake.ml.feature_store import Feature\n\ntxn_features = [\n    Feature.sum(\"TRANSACTION_AMOUNT\", \"1h\").alias(\"SUM_AMT_1H\"),\n    Feature.sum(\"TRANSACTION_AMOUNT\", \"24h\").alias(\"SUM_AMT_24H\"),\n    Feature.count(\"TRANSACTION_AMOUNT\", \"24h\").alias(\"TXN_COUNT_24H\"),\n    Feature.avg(\"TRANSACTION_AMOUNT\", \"7d\").alias(\"AVG_AMT_7D\"),\n]\n\ntxn_df = session.table(\"FRAUD_OFS_DEMO_DB.SOURCE_DATA.TRANSACTIONS\")\n\ntxn_agg_fv = FeatureView(\n    name=\"CUSTOMER_TXN_AGG\",\n    entities=[customer_entity],\n    feature_df=txn_df,\n    features=txn_features,\n    timestamp_col=\"TRANSACTION_TS\",\n    refresh_freq=\"1m\",\n    feature_granularity=\"1 minute\",\n    online_config=OnlineConfig(\n        enable=True,\n        store_type=OnlineStoreType.POSTGRES,\n    ),\n    desc=\"Rolling transaction aggregations: sum, count, avg over 1h/24h/7d windows\",\n)\n\nregistered_txn_fv = fs.register_feature_view(txn_agg_fv, \"V1\", overwrite=True)\nprint(f\"Registered: {registered_txn_fv.name}/{registered_txn_fv.version}\")\n```\n\n### Stream Feature View: Transaction Velocity\n\nStream Feature Views ingest events in real time and serve updated features with 2-3 second end-to-end freshness.\n\n#### Register a Stream Source\n\n```python\nfrom snowflake.ml.feature_store import StreamSource, StreamConfig\nfrom snowflake.snowpark.types import (\n    StructType, StructField, StringType, FloatType,\n    TimestampType, TimestampTimeZone,\n)\n\ntxn_stream = StreamSource(\n    name=\"TXN_EVENTS\",\n    schema=StructType([\n        StructField(\"CUSTOMER_ID\", StringType()),\n        StructField(\"TRANSACTION_TS\", TimestampType(TimestampTimeZone.NTZ)),\n        StructField(\"TRANSACTION_AMOUNT\", FloatType()),\n        StructField(\"MERCHANT_CATEGORY\", StringType()),\n    ]),\n    desc=\"Real-time transaction events for velocity features\",\n)\nfs.register_stream_source(txn_stream)\n```\n\n#### Define Transformation and Register\n\nDefine a Python transformation function that runs on each ingested event. The `backfill_df` provides historical data so the online store is pre-populated before any new events arrive.\n\n```python\nimport pandas as pd\n\ndef compute_velocity(df: pd.DataFrame) -\u003E pd.DataFrame:\n    \"\"\"Flag high-velocity transactions.\"\"\"\n    df[\"IS_HIGH_AMOUNT\"] = (df[\"TRANSACTION_AMOUNT\"] \u003E 500).astype(int)\n    return df\n\nbackfill_df = session.table(\"FRAUD_OFS_DEMO_DB.SOURCE_DATA.TRANSACTIONS\")\n\nstream_fv = FeatureView(\n    name=\"TXN_STREAM_VELOCITY\",\n    entities=[customer_entity],\n    timestamp_col=\"TRANSACTION_TS\",\n    stream_config=StreamConfig(\n        stream_source=txn_stream,\n        transformation_fn=compute_velocity,\n        backfill_df=backfill_df,\n    ),\n    online_config=OnlineConfig(\n        enable=True,\n        target_lag=\"10s\",\n        store_type=OnlineStoreType.POSTGRES,\n    ),\n    desc=\"Stream-ingested transaction velocity: per-event features with 2-3s freshness\",\n)\n\nregistered_stream_fv = fs.register_feature_view(stream_fv, \"V1\", overwrite=True)\nprint(f\"Registered: {registered_stream_fv.name}/{registered_stream_fv.version}\")\n```\n\n\u003C!-- ------------------------ --\u003E\n## Online Feature Retrieval\n\n### Read Features from the Online Store\n\nRetrieve feature values by entity key with low latency:\n\n```python\nfv = fs.get_feature_view(\"CUSTOMER_PROFILE_FEATURES\", \"V1\")\n\nonline_df = fs.read_feature_view(\n    fv,\n    keys=[[\"CUST_000001\"], [\"CUST_000042\"]],\n    store_type=\"online\",\n)\nonline_df.show()\n```\n\n### Read Multiple Feature Views\n\n```python\ntxn_fv = fs.get_feature_view(\"CUSTOMER_TXN_AGG\", \"V1\")\n\ntxn_online = fs.read_feature_view(\n    txn_fv,\n    keys=[[\"CUST_000001\"]],\n    store_type=\"online\",\n)\ntxn_online.show()\n```\n\n### Latency Expectations\n\nThe Postgres online store achieves:\n- **p50**: sub-10ms\n- **p95**: sub-15ms\n- **p99**: sub-20ms\n\nFor benchmarking in your own environment, see the [Online Feature Store Benchmark Kit](https://github.com/Snowflake-Labs/snowflake-feature-store-online-benchmark-kit).\n\n\u003C!-- ------------------------ --\u003E\n## Stream Ingestion\n\n### Ingest Events via Python SDK\n\nUse `fs.stream_ingest()` to push events in real time. Ingested events are available in the online store within 2-3 seconds.\n\n```python\nimport time\nfrom datetime import datetime\n\n# Ingest a new transaction event\nfs.stream_ingest(\n    stream_source=\"TXN_EVENTS\",\n    records=[\n        {\n            \"CUSTOMER_ID\": \"CUST_000042\",\n            \"TRANSACTION_TS\": datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"),\n            \"TRANSACTION_AMOUNT\": 2500.00,\n            \"MERCHANT_CATEGORY\": \"electronics\",\n        }\n    ],\n)\nprint(\"Event ingested. Waiting for online store to update...\")\ntime.sleep(3)\n\n# Verify the update\nstream_fv = fs.get_feature_view(\"TXN_STREAM_VELOCITY\", \"V1\")\nresult = fs.read_feature_view(\n    stream_fv,\n    keys=[[\"CUST_000042\"]],\n    store_type=\"online\",\n)\nresult.show()\n```\n\n### Before/After Comparison\n\nThis demonstrates the end-to-end freshness of stream ingestion. We read the feature value before ingesting a new event, wait 3 seconds, then read again. You should see `IS_HIGH_AMOUNT` flip to `1` after the high-value transaction is ingested — confirming that the online store updates within seconds.\n\n```python\n# Read before ingest\nbefore = fs.read_feature_view(stream_fv, keys=[[\"CUST_000042\"]], store_type=\"online\")\nprint(\"BEFORE:\", before.to_pandas().to_string(index=False))\n\n# Ingest suspicious transaction\nfs.stream_ingest(\"TXN_EVENTS\", records=[{\n    \"CUSTOMER_ID\": \"CUST_000042\",\n    \"TRANSACTION_TS\": datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"),\n    \"TRANSACTION_AMOUNT\": 5000.00,\n    \"MERCHANT_CATEGORY\": \"crypto_exchange\",\n}])\ntime.sleep(3)\n\n# Read after ingest\nafter = fs.read_feature_view(stream_fv, keys=[[\"CUST_000042\"]], store_type=\"online\")\nprint(\"AFTER:\", after.to_pandas().to_string(index=False))\n```\n\n\u003C!-- ------------------------ --\u003E\n## REST API: Query and Ingest\n\nThe online service exposes HTTP endpoints for feature retrieval and stream ingestion. These can be called from any client (Python, curl, application code).\n\n### Get Endpoint URLs\n\nIn Python, retrieve the URLs from the online service status:\n\n```python\nfrom snowflake.ml.feature_store import online_service\n\nstatus = fs.get_online_service_status()\nquery_url = online_service.endpoint_url(status, \"query\")\ningest_url = online_service.endpoint_url(status, \"ingest\")\n\nprint(f\"Query: {query_url}\")\nprint(f\"Ingest: {ingest_url}\")\n```\n\n### Query Endpoint\n\nRetrieve features via the REST query API:\n\n```bash\nexport SNOWFLAKE_PAT=\"\u003Cyour_pat_token\u003E\"\nexport QUERY_URL=\"\u003Cquery_endpoint_url\u003E\"\n\ncurl -s -X POST \"$QUERY_URL/api/v1/query\" \\\n  -H \"Authorization: Snowflake Token=\\\"$SNOWFLAKE_PAT\\\"\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"feature_view\": \"CUSTOMER_TXN_AGG\",\n    \"version\": \"V1\",\n    \"keys\": [[\"CUST_000001\"], [\"CUST_000042\"]]\n  }'\n```\n\n### Ingest Endpoint\n\nPush events via the REST ingest API:\n\n```bash\nexport INGEST_URL=\"\u003Cingest_endpoint_url\u003E\"\n\ncurl -s -X POST \"$INGEST_URL/api/v1/ingest\" \\\n  -H \"Authorization: Snowflake Token=\\\"$SNOWFLAKE_PAT\\\"\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"stream_source\": \"TXN_EVENTS\",\n    \"records\": [\n      {\n        \"CUSTOMER_ID\": \"CUST_000042\",\n        \"TRANSACTION_TS\": \"2026-07-30 10:15:00\",\n        \"TRANSACTION_AMOUNT\": 3200.00,\n        \"MERCHANT_CATEGORY\": \"jewelry\"\n      }\n    ]\n  }'\n```\n\n\u003C!-- ------------------------ --\u003E\n## Model Registry Integration\n\nThe Online Feature Store integrates with the Snowflake Model Registry. When deploying a model as a service, you can configure automatic feature retrieval so the inference endpoint only needs entity IDs.\n\n\u003E NOTE:\n\u003E Model training is handled in the notebook. The notebook uses `fs.generate_training_set()` to create a point-in-time correct training dataset from the Feature Views above, then trains an XGBoost fraud classifier. See the notebook for full training details.\n\n### Log Model to Registry\n\nAfter training in the notebook, the model is registered:\n\n```python\nfrom snowflake.ml.registry import Registry\n\nregistry = Registry(session=session)\n\nmv = registry.log_model(\n    model=trained_model,\n    model_name=\"FRAUD_DETECTION_MODEL\",\n    version_name=\"V1\",\n    metrics={\"auc\": auc_score, \"f1\": f1_score},\n)\n```\n\n### Deploy with Automatic Feature Retrieval\n\nPass `feature_sources_per_function` to have the service automatically look up features from the online store at inference time. You only need to send the entity ID (`CUSTOMER_ID`) in the request.\n\n```python\nmv.create_service(\n    service_name=\"FRAUD_SCORING_SVC\",\n    service_compute_pool=\"ML_INFERENCE_POOL\",\n    ingress_enabled=True,\n    feature_sources_per_function={\n        \"predict\": [registered_profile_fv, registered_txn_fv],\n    },\n)\n```\n\nWith this configuration, a prediction request only needs:\n```json\n{\"CUSTOMER_ID\": \"CUST_000042\"}\n```\n\nThe service fetches `CUSTOMER_PROFILE_FEATURES` and `CUSTOMER_TXN_AGG` from the online store automatically before invoking the model.\n\n\u003C!-- ------------------------ --\u003E\n## Clean Up\n\n### Drop the Online Service\n\nThe Postgres online service runs continuously. Drop it from the notebook when done:\n\n```python\nfs.drop_online_service()\n```\n\n### Run the Teardown Script\n\n1. Open Snowflake and navigate to **Projects** \u003E **Workspaces**\n2. Create a new SQL file and paste the following:\n\n```sql\nUSE ROLE ACCOUNTADMIN;\n\nSET USERNAME = (SELECT CURRENT_USER());\n\n-- Drop online service resources (handled by fs.drop_online_service() above)\n-- Drop database (drops all schemas, tables, feature views, dynamic tables)\nUSE ROLE FS_DEMO_ROLE;\nDROP DATABASE IF EXISTS FRAUD_OFS_DEMO_DB;\nDROP WAREHOUSE IF EXISTS FS_DEMO_WH;\nDROP COMPUTE POOL IF EXISTS FS_DEMO_INFERENCE_POOL;\n\n-- Drop integration and role\nUSE ROLE ACCOUNTADMIN;\nDROP INTEGRATION IF EXISTS FRAUD_OFS_DEMO_ALLOW_ALL_INTEGRATION;\n\nREVOKE CREATE DATABASE ON ACCOUNT FROM ROLE FS_DEMO_ROLE;\nREVOKE CREATE WAREHOUSE ON ACCOUNT FROM ROLE FS_DEMO_ROLE;\nREVOKE CREATE COMPUTE POOL ON ACCOUNT FROM ROLE FS_DEMO_ROLE;\nREVOKE BIND SERVICE ENDPOINT ON ACCOUNT FROM ROLE FS_DEMO_ROLE;\nREVOKE IMPORT SHARE ON ACCOUNT FROM ROLE FS_DEMO_ROLE;\nREVOKE EXECUTE TASK ON ACCOUNT FROM ROLE FS_DEMO_ROLE;\nREVOKE EXECUTE MANAGED TASK ON ACCOUNT FROM ROLE FS_DEMO_ROLE;\n\nREVOKE ROLE FS_DEMO_ROLE FROM USER identifier($USERNAME);\nDROP ROLE IF EXISTS FS_DEMO_ROLE;\n\nSELECT 'Teardown complete.' AS STATUS;\n```\n\n\u003C!-- ------------------------ --\u003E\n## Conclusion and Resources\n\nCongratulations! You've built a real-time fraud detection system using the Snowflake Online Feature Store with Postgres.\n\n### What You Learned\n- How to create a Postgres-backed online service with `create_online_service()`\n- How to register batch, aggregation, and stream Feature Views with `OnlineStoreType.POSTGRES`\n- How to retrieve online features with low latency\n- How to ingest streaming events with 2-3 second end-to-end freshness\n- How to use the REST API endpoints for feature query and stream ingest\n- How to integrate with Model Registry for automatic feature retrieval at inference time\n\n### Key Takeaways\n- **Postgres Online Store** delivers p50 ~5-10ms in-region latency via the REST query API\n- **Time-windowed aggregations** (`Feature.sum/count/avg`) compute rolling metrics automatically\n- **Stream Feature Views** provide 2-3 second freshness via REST ingest\n- **REST API** enables language-agnostic integration (curl, Python, any HTTP client)\n- **`feature_sources_per_function`** eliminates the need for clients to fetch features manually\n\n### Related Resources\n- [Serving Online Features (Postgres)](https://docs.snowflake.com/en/developer-guide/snowflake-ml/feature-store/online-feature-store)\n- [Online Feature Store Quickstart Notebook](assets/online_feature_store_fraud_detection.ipynb)\n- [Snowflake Feature Store Documentation](https://docs.snowflake.com/en/developer-guide/snowflake-ml/feature-store/overview)\n- [Ingest API Reference](https://docs.snowflake.com/developer-guide/snowflake-ml/feature-store/online-feature-store-ingest-api-reference)\n- [Query API Reference](https://docs.snowflake.com/developer-guide/snowflake-ml/feature-store/online-feature-store-query-api-reference)\n- [Online Feature Store Benchmark Kit](https://github.com/Snowflake-Labs/snowflake-feature-store-online-benchmark-kit)\n- [Real-time Inference with Online Feature Store](https://docs.snowflake.com/developer-guide/snowflake-ml/inference/real-time-inference-rest-api#label-real-time-inference-online-feature-store-integration)\n- [Advanced Feature Engineering (Aggregations)](https://docs.snowflake.com/developer-guide/snowflake-ml/feature-store/advanced-feature-engineering)\n- [Programmatic Access Tokens](https://docs.snowflake.com/user-guide/programmatic-access-tokens)\n\n### Next Steps\n\n- Try the feature store with your own datasets\n- Integrate online features into production applications via the REST query API","title":"Quickstart Article Body","multiValue":false,":type":"text/x-markdown"},"quickstartArticleLogoImage":{"dataType":"string","title":"Quickstart Article Logo Image","multiValue":false,":type":"text/plain"}},"elementsOrder":["quickstartArticleBody","quickstartArticleLogoImage"]},"flexible_column_cont":{"id":"flexible-column-container-5118a0debe","type":"2-column-75-25","alignColumns":"top","containerMaxWidth":"extra-large","topPadding":"none","bottomPadding":"none","spaceBetween":"none","reverseOnMobile":false,"carouselOnMobile":false,"backgroundImageOption":"none","flexible_column_content_container_1":{"id":"container-f4311c7cc1","layout":"SIMPLE",":type":"snowflake-site/components/flexible-column-container/flexible-column-content-container",":items":{"quickstart_last_modi":{"id":"quickstart-last-modified-6afe0c4677","icon":{"id":"icon","icon":"calendar",":type":"snowflake-site/components/icon","appliedCssClassNames":"snowflake-icon-blue"},"lastModifiedDatePrefix":"Updated","lastModifiedDate":"2026-08-28",":type":"snowflake-site/components/quickstart/quickstart-last-modified","appliedCssClassNames":"snowflake-responsive-component-top-padding-small"},"text":{"id":"text-237793d849","additionalClasses":"qs-disclaimer-text","text":"\u003Cp\u003E\u003Cspan style=\"color: #666;\"\u003EThis content is provided as is, and is not maintained on an ongoing basis. It may be out of date with current Snowflake instances\u003C/span\u003E\u003C/p\u003E\r\n","richText":true,":type":"snowflake-site/components/text","appliedCssClassNames":"snowflake-responsive-component-top-padding-small"}},":itemsOrder":["quickstart_last_modi","text"]},"flexible_column_content_container_2":{"id":"container-4c7a9306fe","layout":"SIMPLE",":type":"snowflake-site/components/flexible-column-container/flexible-column-content-container",":items":{},":itemsOrder":[]},"isBlogPage":false,"isActiveTOC":false,":type":"snowflake-site/components/flexible-column-container"}},":itemsOrder":["contentfragment","flexible_column_cont"]},"flexible_column_content_container_2":{"id":"container-b3e5cfa58d","layout":"SIMPLE",":type":"snowflake-site/components/flexible-column-container/flexible-column-content-container",":items":{"quickstart_table_of_":{"id":"container-e26ba8319f","layout":"SIMPLE","isDeveloperGuidesPage":false,":type":"snowflake-site/components/quickstart/quickstart-table-of-content/quickstart-table-of-content-container",":items":{"quickstart_table_of_":{"id":"quickstart-table-of-content-c4c4e1c6e1","fragmentPath":"/content/dam/snowflake-site/en/content-fragments/quickstarts/base-quickstart-cf",":type":"snowflake-site/components/quickstart/quickstart-table-of-content","headings":["\u003Ch2\u003EOverview\u003C/h2\u003E","\u003Ch2\u003ESetup and Data Preparation\u003C/h2\u003E","\u003Ch2\u003EInitialize Feature Store\u003C/h2\u003E","\u003Ch2\u003ECreate Online Service\u003C/h2\u003E","\u003Ch2\u003ERegister Feature Views\u003C/h2\u003E","\u003Ch2\u003EOnline Feature Retrieval\u003C/h2\u003E","\u003Ch2\u003EStream Ingestion\u003C/h2\u003E","\u003Ch2\u003EREST API: Query and Ingest\u003C/h2\u003E","\u003Ch2\u003EModel Registry Integration\u003C/h2\u003E","\u003Ch2\u003EClean Up\u003C/h2\u003E","\u003Ch2\u003EConclusion and Resources\u003C/h2\u003E"]},"quickstart_button":{"id":"quickstart-button-e201d22351","fragmentPath":"/content/dam/snowflake-site/en/content-fragments/quickstarts/base-quickstart-cf",":type":"snowflake-site/components/quickstart/quickstart-button","appliedCssClassNames":"snowflake-responsive-component-top-padding-none"}},":itemsOrder":["quickstart_table_of_","quickstart_button"]}},":itemsOrder":["quickstart_table_of_"]},"isBlogPage":false,"isActiveTOC":false,":type":"snowflake-site/components/flexible-column-container"},"markup_editor":{"id":"markup-editor-df485b8d04","title":"Page CSS","cssContent":"#quickstart-template-main-flexible-container{padding:24px}#quickstart-template-main-flexible-container \u003E .snowflake-flexible-column-container-items{grid-template-columns:1fr 0}.qs-disclaimer-text p \u003E span{font-size:15px !important}@media (min-width:768px){#quickstart-template-main-flexible-container{padding:24px 32px}#quickstart-template-main-flexible-container \u003E .snowflake-flexible-column-container-items{grid-template-columns:7fr 3fr;gap:48px}}@media (max-width:767px){#quickstart-template-main-flexible-container \u003E .snowflake-flexible-column-container-items{gap:0}}@media (min-width:1024px){#quickstart-template-main-flexible-container{padding:0 92px 48px 92px}#quickstart-template-main-flexible-container \u003E .snowflake-flexible-column-container-items{gap:117px}}","isGSAPEnabled":false,":type":"snowflake-site/components/markup-editor"}},":itemsOrder":["quickstart_hero","flexible_column_cont","markup_editor"],":type":"wcm/foundation/components/responsivegrid"},"modal_container":{"id":"container-a0ef785d54","layout":"SIMPLE",":type":"snowflake-site/components/modal/modal-container",":items":{},":itemsOrder":[]},"experiencefragment-footer":{"id":"experiencefragment-01a8d10f4a","localizedFragmentVariationPath":"/content/experience-fragments/snowflake-site/language-masters/en/site/footer/master/jcr:content","configured":true,"xfModelPath":"/content/experience-fragments/snowflake-site/language-masters/en/site/footer/master.xfmodel.json",":type":"snowflake-site/components/experiencefragment"},"markup_editor":{"id":"markup-editor-2e62693e7f","title":"Quickstarts Overrides","cssContent":".snowflake-markdown blockquote{padding:24px 32px;background:#f6f9fa;border:1px solid #29b5e8;border-radius:16px}.snowflake-markdown .snowflake-image-container img{width:auto !important;max-width:100%}.snowflake-markdown .snowflake-text ol{padding-left:20px !important}.snowflake-markdown .snowflake-text li{margin:0 0 12px 0 !important}.snowflake-markdown h3.snowflake-markdown-h3{font-size:20px !important;font-family:Texta,sans-serif !important}@media (min-width:768px){.snowflake-markdown h3.snowflake-markdown-h3{font-size:28px !important}}","isGSAPEnabled":false,":type":"snowflake-site/components/markup-editor"}},":itemsOrder":["experiencefragment-banner","experiencefragment-header","markup_editor_1950346551","responsivegrid","modal_container","experiencefragment-footer","markup_editor"],":type":"wcm/foundation/components/responsivegrid"}},":itemsOrder":["root"],":hierarchyType":"page"}
  