<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:media="http://search.yahoo.com/mrss/" >

<channel>
	<title>Tuyen Nguyen | Qilin.Cloud</title>
	<atom:link href="https://qilin.cloud/author/t-nguyen/feed/" rel="self" type="application/rss+xml" />
	<link>https://qilin.cloud</link>
	<description>Technology Platform for composable e-commerce</description>
	<lastBuildDate>Thu, 26 Mar 2026 11:07:31 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0.1</generator>

<image>
	<url>https://qilin.cloud/wp-content/uploads/2023/08/cropped-QilinCloud-Logo-32x32.png</url>
	<title>Tuyen Nguyen | Qilin.Cloud</title>
	<link>https://qilin.cloud</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Connector Manifests: The Secret to Onboarding Channels Without a Thousand Checkboxes</title>
		<link>https://qilin.cloud/connector-manifest-dynamic-ui-faster-onboarding/</link>
		
		<dc:creator><![CDATA[Tuyen Nguyen]]></dc:creator>
		<pubDate>Tue, 30 Jun 2026 08:00:00 +0000</pubDate>
				<category><![CDATA[Engineering Deep Dives]]></category>
		<category><![CDATA[configuration]]></category>
		<category><![CDATA[connectors]]></category>
		<category><![CDATA[developer experience]]></category>
		<category><![CDATA[onboarding]]></category>
		<category><![CDATA[partners]]></category>
		<guid isPermaLink="false">https://qilin.cloud/?p=3786</guid>

					<description><![CDATA[<p>A connector should describe itself: capabilities, auth needs, limits, and settings. Manifests turn onboarding into a predictable product experience.</p>
<p>The post <a rel="nofollow" href="https://qilin.cloud/connector-manifest-dynamic-ui-faster-onboarding/">Connector Manifests: The Secret to Onboarding Channels Without a Thousand Checkboxes</a> appeared first on <a rel="nofollow" href="https://qilin.cloud">Qilin.Cloud</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="et_pb_section et_pb_section_0 et_section_regular" >
				
				
				
				
				
				
				<div class="et_pb_row et_pb_row_0">
				<div class="et_pb_column et_pb_column_4_4 et_pb_column_0  et_pb_css_mix_blend_mode_passthrough et-last-child">
				
				
				
				
				<div class="et_pb_module et_pb_text et_pb_text_0  et_pb_text_align_left et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_text_inner"><p>Channel onboarding has a long-standing “classic” workflow:</p>
<ul>
<li>read a wiki page</li>
<li>copy credentials into a config file</li>
<li>set 14 environment variables</li>
<li>run a script</li>
<li>discover you missed variable #11</li>
<li>repeat until you achieve enlightenment (or madness)</li>
</ul>
<p>That’s not a rite of passage we want to preserve.</p>
<p>In this June deep dive, we’ll look at an idea that sounds simple &#8211; but changes everything:</p>
<p><strong>Connectors should describe themselves.</strong></p>
<p>Enter: <em><strong>Connector Manifests.</strong></em></p></div>
			</div>
			</div>
				
				
				
				
			</div><div class="et_pb_row et_pb_row_1">
				<div class="et_pb_column et_pb_column_4_4 et_pb_column_1  et_pb_css_mix_blend_mode_passthrough et-last-child">
				
				
				
				
				<div class="et_pb_module pac_divi_table_of_contents pac_divi_table_of_contents_0">
				
				
				
				
				
				
				<div class="et_pb_module_inner">
					
        <div class="pac_dtoc_main_container"
        data-allow_collapse_minimize="on"
        data-allow_collapse_minimize_tablet="on"
        data-allow_collapse_minimize_phone="on"
        data-ss="2000"
        data-sah="100"
        data-collapse_when_sticky="off"
        data-collapse_when_sticky_tablet="off"
        data-collapse_when_sticky_phone="off"
        data-skh="off"
        data-mtocai="off"
        data-mtocai_tablet="off"
        data-mtocai_phone="off"
        data-alh="off"
        data-ds="closed"
        data-dst="closed"
        data-dsp="closed">
            <div class="pac_dtoc_title_area click_on click_tablet_on click_phone_on">
                <div role="heading" aria-level="2" id="pac_dtocm_title" class="pac_dtoc_title">Table of Contents</div>
                
                <div class="pac_dtoc_icon_responsive">
                    <div class="pac_dtoc_opened_icon">2</div>
                    <div class="pac_dtoc_closed_icon">3</div>
                </div>
                
            </div>
            <div role="navigation" aria-labelledby="pac_dtocm_title" class="pac_dtoc_body_area inside">
                
                <div class='divi_table_of_contents' role="tree" ><ul class="pac_dtoc_heading_level_1" role="group" ><li class="pac_dtoc_li_heading_level_1" role="treeitem" ><div role="presentation" ><span data-href='#pac_remove_first_heading' data-hl='1'></span><a href='#pac_remove_first_heading' id='pac_remove_first_heading_toc_headding'>FirstHeading</a></div></li><ul class="pac_dtoc_heading_level_2" role="group" ><li class="pac_dtoc_li_heading_level_2" role="treeitem" ><div role="presentation" ><span data-href='#Thepainonboardingisusuallyhiddencomplexity' data-hl='2'></span><a href='#Thepainonboardingisusuallyhiddencomplexity' id='Thepainonboardingisusuallyhiddencomplexity_toc_headding'>The pain: onboarding is usually hidden complexity</a></div></li><li class="pac_dtoc_li_heading_level_2" role="treeitem" ><div role="presentation" ><span data-href='#Theideamakeonboardingmetadataexplicit' data-hl='2'></span><a href='#Theideamakeonboardingmetadataexplicit' id='Theideamakeonboardingmetadataexplicit_toc_headding'>The idea: make onboarding metadata explicit</a></div></li><li class="pac_dtoc_li_heading_level_2" role="treeitem" ><div role="presentation" ><span data-href='#Whataconnectormanifesttypicallycontains' data-hl='2'></span><a href='#Whataconnectormanifesttypicallycontains' id='Whataconnectormanifesttypicallycontains_toc_headding'>What a connector manifest typically contains</a></div></li><ul class="pac_dtoc_heading_level_3" role="group" ><li class="pac_dtoc_li_heading_level_3" role="treeitem" ><div role="presentation" ><span data-href='#1Identityversion' data-hl='3'></span><a href='#1Identityversion' id='1Identityversion_toc_headding'>1) Identity &amp; version</a></div></li><li class="pac_dtoc_li_heading_level_3" role="treeitem" ><div role="presentation" ><span data-href='#2Authentication' data-hl='3'></span><a href='#2Authentication' id='2Authentication_toc_headding'>2) Authentication</a></div></li><li class="pac_dtoc_li_heading_level_3" role="treeitem" ><div role="presentation" ><span data-href='#3Settingsschema' data-hl='3'></span><a href='#3Settingsschema' id='3Settingsschema_toc_headding'>3) Settings schema</a></div></li><li class="pac_dtoc_li_heading_level_3" role="treeitem" ><div role="presentation" ><span data-href='#4Capabilitieslimits' data-hl='3'></span><a href='#4Capabilitieslimits' id='4Capabilitieslimits_toc_headding'>4) Capabilities &amp; limits</a></div></li></ul><li class="pac_dtoc_li_heading_level_2" role="treeitem" ><div role="presentation" ><span data-href='#Whythisisabigdealforagenciesandpartners' data-hl='2'></span><a href='#Whythisisabigdealforagenciesandpartners' id='Whythisisabigdealforagenciesandpartners_toc_headding'>Why this is a big deal for agencies and partners</a></div></li><li class="pac_dtoc_li_heading_level_2" role="treeitem" ><div role="presentation" ><span data-href='#Atinyillustrativeexample' data-hl='2'></span><a href='#Atinyillustrativeexample' id='Atinyillustrativeexample_toc_headding'>A tiny illustrative example</a></div></li><li class="pac_dtoc_li_heading_level_2" role="treeitem" ><div role="presentation" ><span data-href='#TheconnectivetissueauthenticationbetweenQilinandconnectors' data-hl='2'></span><a href='#TheconnectivetissueauthenticationbetweenQilinandconnectors' id='TheconnectivetissueauthenticationbetweenQilinandconnectors_toc_headding'>The connective tissue: authentication between Qilin and connectors</a></div></li><li class="pac_dtoc_li_heading_level_2" role="treeitem" ><div role="presentation" ><span data-href='#Whythismattersdependingonwhoyouare' data-hl='2'></span><a href='#Whythismattersdependingonwhoyouare' id='Whythismattersdependingonwhoyouare_toc_headding'>Why this matters (depending on who you are)</a></div></li><ul class="pac_dtoc_heading_level_3" role="group" ><li class="pac_dtoc_li_heading_level_3" role="treeitem" ><div role="presentation" ><span data-href='#Developers' data-hl='3'></span><a href='#Developers' id='Developers_toc_headding'>Developers</a></div></li><li class="pac_dtoc_li_heading_level_3" role="treeitem" ><div role="presentation" ><span data-href='#Agenciesintegrators' data-hl='3'></span><a href='#Agenciesintegrators' id='Agenciesintegrators_toc_headding'>Agencies &amp; integrators</a></div></li><li class="pac_dtoc_li_heading_level_3" role="treeitem" ><div role="presentation" ><span data-href='#Merchants' data-hl='3'></span><a href='#Merchants' id='Merchants_toc_headding'>Merchants</a></div></li><li class="pac_dtoc_li_heading_level_3" role="treeitem" ><div role="presentation" ><span data-href='#Investors' data-hl='3'></span><a href='#Investors' id='Investors_toc_headding'>Investors</a></div></li></ul><li class="pac_dtoc_li_heading_level_2" role="treeitem" ><div role="presentation" ><span data-href='#Theoldwisdomstillholds' data-hl='2'></span><a href='#Theoldwisdomstillholds' id='Theoldwisdomstillholds_toc_headding'>The old wisdom (still holds)</a></div></li></ul></div>
            </div>
        </div>
        
				</div>
			</div>
			</div>
				
				
				
				
			</div><div class="et_pb_row et_pb_row_6">
				<div class="et_pb_column et_pb_column_4_4 et_pb_column_6  et_pb_css_mix_blend_mode_passthrough et-last-child">
				
				
				
				
				<div class="et_pb_module et_pb_blurb et_pb_blurb_8  et_pb_text_align_left  et_pb_blurb_position_top et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_blurb_content">
					
					<div class="et_pb_blurb_container">
						<h2 class="et_pb_module_header"><span>The pain: onboarding is usually hidden complexity</span></h2>
						<div class="et_pb_blurb_description"><p>A connector isn’t “just an API client”.</p>
<p>It has:</p>
<ul>
<li>authentication requirements</li>
<li>required and optional settings</li>
<li>supported capabilities (read, write, update-only, webhooks…)</li>
<li>constraints (batch size, rate limits, required identifiers)</li>
<li>and sometimes UI configuration that differs per channel</li>
</ul>
<p>If every connector encodes that knowledge only in code or tribal memory, you get:</p>
<ul>
<li>brittle onboarding</li>
<li>inconsistent setups</li>
<li>and support tickets that start with “did you set the correct storefront?”</li>
</ul></div>
					</div>
				</div>
			</div>
			</div>
				
				
				
				
			</div><div class="et_pb_row et_pb_row_7">
				<div class="et_pb_column et_pb_column_4_4 et_pb_column_7  et_pb_css_mix_blend_mode_passthrough et-last-child">
				
				
				
				
				<div class="et_pb_module et_pb_blurb et_pb_blurb_9  et_pb_text_align_left  et_pb_blurb_position_top et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_blurb_content">
					
					<div class="et_pb_blurb_container">
						<h2 class="et_pb_module_header"><span>The idea: make onboarding metadata explicit</span></h2>
						<div class="et_pb_blurb_description"><p>A <strong>Connector Manifest</strong> is a structured description of:</p>
<ul>
<li><strong>who the connector is</strong></li>
<li><strong>what it supports</strong></li>
<li><strong>what it needs to run</strong></li>
<li><strong>how users should configure it</strong></li>
</ul>
<p>Once the platform has that information, it can do useful things automatically:</p>
<ul>
<li>render configuration screens dynamically</li>
<li>validate settings before you hit “save”</li>
<li>guide users through onboarding steps</li>
<li>keep docs and UI in sync</li>
</ul>
<p>This is how onboarding becomes a product feature &#8211; not a scavenger hunt.</p></div>
					</div>
				</div>
			</div><div class="et_pb_module et_pb_blurb et_pb_blurb_10  et_pb_text_align_left  et_pb_blurb_position_top et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_blurb_content">
					
					<div class="et_pb_blurb_container">
						<h2 class="et_pb_module_header"><span>What a connector manifest typically contains</span></h2>
						<div class="et_pb_blurb_description"><p>Conceptually, a manifest covers:</p>
<p>&nbsp;</p>
<h3>1) Identity &amp; version</h3>
<ul>
<li>name</li>
<li>version</li>
<li>compatibility range</li>
</ul>
<h3>2) Authentication</h3>
<ul>
<li>supported auth types (API key, OAuth2, etc.)</li>
<li>required secrets (stored in credential management)</li>
<li>scope requirements</li>
</ul>
<h3>3) Settings schema</h3>
<ul>
<li>keys, types, defaults</li>
<li>required fields</li>
<li>validation rules</li>
<li>UI hints (labels, help text, grouping)</li>
</ul>
<h3>4) Capabilities &amp; limits</h3>
<ul>
<li>supported operations (e.g., offer.update, product.sync, order.import)</li>
<li>batch constraints</li>
<li>known rate-limit behavior</li>
<li>“update-only” vs “create + update” semantics</li>
</ul></div>
					</div>
				</div>
			</div><div class="et_pb_module et_pb_blurb et_pb_blurb_11  et_pb_text_align_left  et_pb_blurb_position_top et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_blurb_content">
					
					<div class="et_pb_blurb_container">
						<h2 class="et_pb_module_header"><span>Why this is a big deal for agencies and partners</span></h2>
						<div class="et_pb_blurb_description"><p>Agencies don’t want “one-off integrations”.</p>
<p>They want repeatable delivery:</p>
<ul>
<li>fewer surprises</li>
<li>faster onboarding</li>
<li>predictable handover</li>
</ul>
<p>Manifests help because they turn connector configuration into something you can standardize:</p>
<ul>
<li>onboarding checklists become consistent</li>
<li>configuration can be validated and exported</li>
<li>documentation can be generated from the same source of truth</li>
</ul>
<p>This is also how you build an ecosystem where partners can ship connectors without forcing every end user to become an expert on that channel’s quirks.</p></div>
					</div>
				</div>
			</div><div class="et_pb_module et_pb_accordion et_pb_accordion_1">
				
				
				
				
				<div class="et_pb_toggle et_pb_module et_pb_accordion_item et_pb_accordion_item_1  et_pb_toggle_open">
				
				
				
				
				<h5 class="et_pb_toggle_title"></h5>
				<div class="et_pb_toggle_content clearfix">We invite you to share your experiences and lessons learned with Qilin.Cloud’s innovative technology platform for composable e-commerce. Your story can inspire others and help the whole community to improve.

&nbsp;
<h4><strong>Share your Qilin.Cloud Success Story</strong>
<span> </span></h4>
<div class="et_pb_button_module_wrapper et_pb_button_0_wrapper  et_pb_module "><a class="et_pb_button et_pb_button_0 et_pb_bg_layout_light" href="https://qilin.cloud/share-your-story/">Your Journey</a></div></div>
			</div>
			</div><div class="et_pb_module et_pb_blurb et_pb_blurb_12  et_pb_text_align_left  et_pb_blurb_position_top et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_blurb_content">
					
					<div class="et_pb_blurb_container">
						<h2 class="et_pb_module_header"><span>A tiny illustrative example</span></h2>
						<div class="et_pb_blurb_description"><p>Here’s a simplified pseudo-manifest, just to show the shape:</p>
<pre>{
  "name": "MarketplaceConnector",
  "version": "1.2.0",
  "auth": { "type": "apiKey", "credentialKey": "marketplace_api_key" },
  "settings": [
    { "key": "storefront", "type": "enum", "values": ["de","cz","sk"], "required": true },
    { "key": "mode", "type": "enum", "values": ["updateOnly","fullSync"], "required": true }
  ],
  "limits": { "maxBatchSize": 150 }
}
</pre>
<p>Now the platform can:</p>
<ul>
<li>show only relevant fields</li>
<li>enforce max batch size</li>
<li>prevent invalid configurations before the first run</li>
</ul>
<p>That’s onboarding maturity.</p></div>
					</div>
				</div>
			</div><div class="et_pb_module et_pb_blurb et_pb_blurb_13  et_pb_text_align_left  et_pb_blurb_position_top et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_blurb_content">
					
					<div class="et_pb_blurb_container">
						<h2 class="et_pb_module_header"><span>The connective tissue: authentication between Qilin and connectors</span></h2>
						<div class="et_pb_blurb_description"><p>Manifests only work if secrets are handled properly.</p>
<p>That’s why this ties directly into:</p>
<ul>
<li>credential management</li>
<li>permissioned access (who can use which secret)</li>
<li>audit logs (who changed what)</li>
<li>and safe rotation</li>
</ul>
<p>You get speed <em>and</em> governance.</p></div>
					</div>
				</div>
			</div><div class="et_pb_module et_pb_blurb et_pb_blurb_14  et_pb_text_align_left  et_pb_blurb_position_top et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_blurb_content">
					
					<div class="et_pb_blurb_container">
						<h2 class="et_pb_module_header"><span>Why this matters (depending on who you are)</span></h2>
						<div class="et_pb_blurb_description"><h3>Developers</h3>
<p>Less custom UI. Less glue code. More time spent on real problems.</p>
<h3>Agencies &amp; integrators</h3>
<p>Faster delivery and fewer onboarding surprises. <br />You can scale services without scaling chaos.</p>
<h3>Merchants</h3>
<p>Onboarding becomes predictable, and “go-live” stops being a heroic act.</p>
<h3>Investors</h3>
<p>Ecosystem extensibility increases TAM (total addressable market). <br />A platform that can onboard channels efficiently can grow faster.</p></div>
					</div>
				</div>
			</div><div class="et_pb_module et_pb_blurb et_pb_blurb_15  et_pb_text_align_left  et_pb_blurb_position_top et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_blurb_content">
					
					<div class="et_pb_blurb_container">
						<h2 class="et_pb_module_header"><span>The old wisdom (still holds)</span></h2>
						<div class="et_pb_blurb_description"><p>Documentation matters. <br />But the best documentation is the kind that can’t go out of date.</p>
<p>Manifests are “docs that compile”.</p></div>
					</div>
				</div>
			</div>
			</div>
				
				
				
				
			</div>
				
				
			</div>
<p>The post <a rel="nofollow" href="https://qilin.cloud/connector-manifest-dynamic-ui-faster-onboarding/">Connector Manifests: The Secret to Onboarding Channels Without a Thousand Checkboxes</a> appeared first on <a rel="nofollow" href="https://qilin.cloud">Qilin.Cloud</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Kaufland Offer Sync (Update-Only): The Safe Way to Keep Price and Stock Fresh</title>
		<link>https://qilin.cloud/kaufland-offer-sync-update-only-safe-price-stock/</link>
		
		<dc:creator><![CDATA[Tuyen Nguyen]]></dc:creator>
		<pubDate>Wed, 31 Dec 2025 08:00:00 +0000</pubDate>
				<category><![CDATA[Product Updates]]></category>
		<category><![CDATA[kaufland]]></category>
		<category><![CDATA[marketplace]]></category>
		<category><![CDATA[offer sync]]></category>
		<category><![CDATA[price]]></category>
		<category><![CDATA[stock]]></category>
		<guid isPermaLink="false">https://qilin.cloud/?p=3738</guid>

					<description><![CDATA[<p>December’s connector milestone: update-only Kaufland offer sync. Clean identification (EAN + condition + storefront), safe updates for price/stock/handling time, and batch exports for real-world volume.</p>
<p>The post <a rel="nofollow" href="https://qilin.cloud/kaufland-offer-sync-update-only-safe-price-stock/">Kaufland Offer Sync (Update-Only): The Safe Way to Keep Price and Stock Fresh</a> appeared first on <a rel="nofollow" href="https://qilin.cloud">Qilin.Cloud</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><div class="et_pb_section et_pb_section_1 et_section_regular" >
				
				
				
				
				
				
				<div class="et_pb_row et_pb_row_8">
				<div class="et_pb_column et_pb_column_4_4 et_pb_column_8  et_pb_css_mix_blend_mode_passthrough et-last-child">
				
				
				
				
				<div class="et_pb_module et_pb_text et_pb_text_2  et_pb_text_align_left et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_text_inner"><p>Commerce marketplaces are not playgrounds.</p>
<p>If you’ve integrated with them long enough, you learn a cautious habit:</p>
<p><strong>Never create or overwrite things by accident.</strong></p>
<p>December’s connector work embraces that cautious, battle-earned mindset with an important milestone:</p>
<p><strong>Kaufland Connector (Update-Only Offer Sync)</strong></p>
<p>At this stage, the connector focuses on the safest and most operationally valuable capability first:</p>
<ul>
<li>updating existing offers (units) for:
<ul>
<li><strong>price</strong></li>
<li><strong>stock</strong></li>
<li><strong>handling time</strong></li>
</ul>
</li>
</ul>
<p>No surprise creations. No accidental duplication. Just clean, controlled updates.</p></div>
			</div>
			</div>
				
				
				
				
			</div><div class="et_pb_row et_pb_row_9">
				<div class="et_pb_column et_pb_column_4_4 et_pb_column_9  et_pb_css_mix_blend_mode_passthrough et-last-child">
				
				
				
				
				<div class="et_pb_module pac_divi_table_of_contents pac_divi_table_of_contents_1">
				
				
				
				
				
				
				<div class="et_pb_module_inner">
					
        <div class="pac_dtoc_main_container"
        data-allow_collapse_minimize="on"
        data-allow_collapse_minimize_tablet="on"
        data-allow_collapse_minimize_phone="on"
        data-ss="2000"
        data-sah="100"
        data-collapse_when_sticky="off"
        data-collapse_when_sticky_tablet="off"
        data-collapse_when_sticky_phone="off"
        data-skh="off"
        data-mtocai="off"
        data-mtocai_tablet="off"
        data-mtocai_phone="off"
        data-alh="off"
        data-ds="closed"
        data-dst="closed"
        data-dsp="closed">
            <div class="pac_dtoc_title_area click_on click_tablet_on click_phone_on">
                <div role="heading" aria-level="2" id="pac_dtocm_title" class="pac_dtoc_title">Table of Contents</div>
                
                <div class="pac_dtoc_icon_responsive">
                    <div class="pac_dtoc_opened_icon">2</div>
                    <div class="pac_dtoc_closed_icon">3</div>
                </div>
                
            </div>
            <div role="navigation" aria-labelledby="pac_dtocm_title" class="pac_dtoc_body_area inside">
                
                <div class='divi_table_of_contents' role="tree" ><ul class="pac_dtoc_heading_level_1" role="group" ><li class="pac_dtoc_li_heading_level_1" role="treeitem" ><div role="presentation" ><span data-href='#pac_remove_first_heading' data-hl='1'></span><a href='#pac_remove_first_heading' id='pac_remove_first_heading_toc_headding'>FirstHeading</a></div></li><ul class="pac_dtoc_heading_level_2" role="group" ><li class="pac_dtoc_li_heading_level_2" role="treeitem" ><div role="presentation" ><span data-href='#Whyupdateonlyisafeaturenotalimitation' data-hl='2'></span><a href='#Whyupdateonlyisafeaturenotalimitation' id='Whyupdateonlyisafeaturenotalimitation_toc_headding'>Why “update-only” is a feature, not a limitation</a></div></li><li class="pac_dtoc_li_heading_level_2" role="treeitem" ><div role="presentation" ><span data-href='#HowQilinidentifiesanexistingKauflandoffer' data-hl='2'></span><a href='#HowQilinidentifiesanexistingKauflandoffer' id='HowQilinidentifiesanexistingKauflandoffer_toc_headding'>How Qilin identifies an existing Kaufland offer</a></div></li><ul class="pac_dtoc_heading_level_3" role="group" ><li class="pac_dtoc_li_heading_level_3" role="treeitem" ><div role="presentation" ><span data-href='#Behavior' data-hl='3'></span><a href='#Behavior' id='Behavior_toc_headding'> Behavior</a></div></li></ul><li class="pac_dtoc_li_heading_level_2" role="treeitem" ><div role="presentation" ><span data-href='#Howtopushofferssinglevsbatch' data-hl='2'></span><a href='#Howtopushofferssinglevsbatch' id='Howtopushofferssinglevsbatch_toc_headding'>How to push offers: single vs batch</a></div></li><li class="pac_dtoc_li_heading_level_2" role="treeitem" ><div role="presentation" ><span data-href='#Bestpracticesthedonthateyourselflateredition' data-hl='2'></span><a href='#Bestpracticesthedonthateyourselflateredition' id='Bestpracticesthedonthateyourselflateredition_toc_headding'>Best practices (the “don’t hate yourself later” edition)</a></div></li><li class="pac_dtoc_li_heading_level_2" role="treeitem" ><div role="presentation" ><span data-href='#Whobenefits' data-hl='2'></span><a href='#Whobenefits' id='Whobenefits_toc_headding'>Who benefits?</a></div></li><ul class="pac_dtoc_heading_level_3" role="group" ><li class="pac_dtoc_li_heading_level_3" role="treeitem" ><div role="presentation" ><span data-href='#Developers' data-hl='3'></span><a href='#Developers' id='Developers_toc_headding'>Developers</a></div></li><li class="pac_dtoc_li_heading_level_3" role="treeitem" ><div role="presentation" ><span data-href='#Merchants' data-hl='3'></span><a href='#Merchants' id='Merchants_toc_headding'>Merchants</a></div></li><li class="pac_dtoc_li_heading_level_3" role="treeitem" ><div role="presentation" ><span data-href='#Agencies' data-hl='3'></span><a href='#Agencies' id='Agencies_toc_headding'>Agencies</a></div></li><li class="pac_dtoc_li_heading_level_3" role="treeitem" ><div role="presentation" ><span data-href='#Investors' data-hl='3'></span><a href='#Investors' id='Investors_toc_headding'>Investors</a></div></li></ul><li class="pac_dtoc_li_heading_level_2" role="treeitem" ><div role="presentation" ><span data-href='#Whatsnext' data-hl='2'></span><a href='#Whatsnext' id='Whatsnext_toc_headding'>What’s next</a></div></li><li class="pac_dtoc_li_heading_level_2" role="treeitem" ><div role="presentation" ><span data-href='#Marketplaceintegrationsrewardcaution' data-hl='2'></span><a href='#Marketplaceintegrationsrewardcaution' id='Marketplaceintegrationsrewardcaution_toc_headding'>Marketplace integrations reward caution</a></div></li></ul></div>
            </div>
        </div>
        
				</div>
			</div>
			</div>
				
				
				
				
			</div><div class="et_pb_row et_pb_row_14">
				<div class="et_pb_column et_pb_column_4_4 et_pb_column_14  et_pb_css_mix_blend_mode_passthrough et-last-child">
				
				
				
				
				<div class="et_pb_module et_pb_blurb et_pb_blurb_23  et_pb_text_align_left  et_pb_blurb_position_top et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_blurb_content">
					
					<div class="et_pb_blurb_container">
						<h2 class="et_pb_module_header"><span>Why “update-only” is a feature, not a limitation</span></h2>
						<div class="et_pb_blurb_description"><p>In marketplaces, “create” is risky.</p>
<p>It’s easy to create the wrong offer with:</p>
<ul>
<li>the wrong condition</li>
<li>the wrong storefront</li>
<li>missing compliance fields</li>
<li>the wrong EAN mapping</li>
<li>inconsistent identifiers</li>
</ul>
<p>Those mistakes can be expensive.</p>
<p>So update-only sync is the disciplined, traditional approach:</p>
<p><em><strong>&gt; First, prove you can update reliably. Then expand scope.</strong></em></p></div>
					</div>
				</div>
			</div>
			</div>
				
				
				
				
			</div><div class="et_pb_row et_pb_row_15">
				<div class="et_pb_column et_pb_column_4_4 et_pb_column_15  et_pb_css_mix_blend_mode_passthrough et-last-child">
				
				
				
				
				<div class="et_pb_module et_pb_blurb et_pb_blurb_24  et_pb_text_align_left  et_pb_blurb_position_top et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_blurb_content">
					
					<div class="et_pb_blurb_container">
						<h2 class="et_pb_module_header"><span>How Qilin identifies an existing Kaufland offer</span></h2>
						<div class="et_pb_blurb_description"><p>In Kaufland, an offer (unit) is uniquely identified by the combination:</p>
<p><strong>**EAN + Condition + Storefront**</strong></p>
<p>That means the connector looks at these three pieces of information to locate the existing unit.</p>
<h3> Behavior</h3>
<ul>
<li><strong>If a matching unit is found</strong> → update price/stock/handling time</li>
<li><strong>If no matching unit is found</strong> → mark the sync as failed with:
<ul>
<li>`Cannot find existing offer`</li>
</ul>
</li>
</ul>
<p>This is the correct kind of strictness. It prevents “phantom offers” from appearing because a mapping was wrong.</p></div>
					</div>
				</div>
			</div><div class="et_pb_module et_pb_accordion et_pb_accordion_3">
				
				
				
				
				<div class="et_pb_toggle et_pb_module et_pb_accordion_item et_pb_accordion_item_3  et_pb_toggle_open">
				
				
				
				
				<h5 class="et_pb_toggle_title"></h5>
				<div class="et_pb_toggle_content clearfix">We invite you to share your experiences and lessons learned with Qilin.Cloud’s innovative technology platform for composable e-commerce. Your story can inspire others and help the whole community to improve.</p>
<p>&nbsp;</p>
<h4><strong>Share your Qilin.Cloud Success Story</strong><br />
<span> </span></h4>
<div class="et_pb_button_module_wrapper et_pb_button_0_wrapper  et_pb_module "><a class="et_pb_button et_pb_button_0 et_pb_bg_layout_light" href="https://qilin.cloud/share-your-story/">Your Journey</a></div></div>
			</div>
			</div><div class="et_pb_module et_pb_blurb et_pb_blurb_25  et_pb_text_align_left  et_pb_blurb_position_top et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_blurb_content">
					
					<div class="et_pb_blurb_container">
						<h2 class="et_pb_module_header"><span>How to push offers: single vs batch</span></h2>
						<div class="et_pb_blurb_description"><p>You can export offers using either:</p>
<ul>
<li>`OutputConnector` (single item)</li>
<li>`OutputConnectorByBatch` (bulk)</li>
</ul>
<p>Batch mode supports up to <strong>150 offers per batch</strong>, which is ideal for real-world offer volume and helps reduce request overhead.</p>
<p>A high-level flow looks like:</p>
<ol>
<li>build a pipeline that produces Offer objects</li>
<li>add an output processor (single or batch)</li>
<li>configure a `targetId` that represents the Kaufland storefront destination</li>
<li>onboard the channel using that same `targetId` so the connector knows where to send updates</li>
</ol>
<p>This keeps the pipeline definition and the channel onboarding aligned &#8211; no hidden mapping magic.</p></div>
					</div>
				</div>
			</div><div class="et_pb_module et_pb_blurb et_pb_blurb_26  et_pb_text_align_left  et_pb_blurb_position_top et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_blurb_content">
					
					<div class="et_pb_blurb_container">
						<h2 class="et_pb_module_header"><span>Best practices (the “don’t hate yourself later” edition)</span></h2>
						<div class="et_pb_blurb_description"><ul>
<li>Always include valid <strong>EAN</strong> and <strong>Condition</strong> on offers. They’re mandatory for correct unit matching.</li>
<li>Treat `targetId` as a stable contract. If it changes, your connector routing changes.</li>
<li>Prefer batch export for high-volume updates. It’s cheaper, faster, and friendlier to APIs.</li>
<li>Use Data Flow Tracking to monitor failures and spot “offer not found” patterns early &#8211; those usually indicate mapping issues.</li>
</ul></div>
					</div>
				</div>
			</div><div class="et_pb_module et_pb_blurb et_pb_blurb_27  et_pb_text_align_left  et_pb_blurb_position_top et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_blurb_content">
					
					<div class="et_pb_blurb_container">
						<h2 class="et_pb_module_header"><span>Who benefits?</span></h2>
						<div class="et_pb_blurb_description"><h3>Developers</h3>
<ul>
<li>clear identification logic (less ambiguity)</li>
<li>safer connector behavior (less risk during rollout)</li>
<li>batch export for operational throughput</li>
</ul>
<h3>Merchants</h3>
<ul>
<li>safer price/stock updates without accidental new offers</li>
<li>predictable behavior under load</li>
<li>cleaner error signals when something isn’t mapped correctly</li>
</ul>
<h3>Agencies</h3>
<ul>
<li>easier rollout strategy: start with updates, validate matching logic, then scale</li>
<li>fewer marketplace “oops moments” during go-live</li>
</ul>
<h3>Investors</h3>
<p>Connector depth expands addressable value. Update-only is a reliable first step toward full lifecycle sync while keeping risk low.</p></div>
					</div>
				</div>
			</div><div class="et_pb_module et_pb_blurb et_pb_blurb_28  et_pb_text_align_left  et_pb_blurb_position_top et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_blurb_content">
					
					<div class="et_pb_blurb_container">
						<h2 class="et_pb_module_header"><span>What’s next</span></h2>
						<div class="et_pb_blurb_description"><p>January will focus on the developer and operations experience again:</p>
<p><strong>pipeline testing mode</strong> and expanded UI capabilities &#8211; so teams can validate flows safely before turning them loose on production channels.</p></div>
					</div>
				</div>
			</div><div class="et_pb_module et_pb_blurb et_pb_blurb_29  et_pb_text_align_left  et_pb_blurb_position_top et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_blurb_content">
					
					<div class="et_pb_blurb_container">
						<h2 class="et_pb_module_header"><span>Marketplace integrations reward caution</span></h2>
						<div class="et_pb_blurb_description"><p>Fast and reckless breaks things.</p>
<p>Slow and deliberate builds trust.</p>
<p>Qilin.Cloud is taking the deliberate path &#8211; because that’s how integrations survive in the real world.</p></div>
					</div>
				</div>
			</div>
			</div>
				
				
				
				
			</div>
				
				
			</div></p>
<p>The post <a rel="nofollow" href="https://qilin.cloud/kaufland-offer-sync-update-only-safe-price-stock/">Kaufland Offer Sync (Update-Only): The Safe Way to Keep Price and Stock Fresh</a> appeared first on <a rel="nofollow" href="https://qilin.cloud">Qilin.Cloud</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Merge, Timeouts, Retries: Reliability Patterns for Composable Pipelines</title>
		<link>https://qilin.cloud/merge-timeouts-retries-reliability-patterns/</link>
		
		<dc:creator><![CDATA[Tuyen Nguyen]]></dc:creator>
		<pubDate>Mon, 30 Jun 2025 08:00:00 +0000</pubDate>
				<category><![CDATA[Product Updates]]></category>
		<category><![CDATA[error handling]]></category>
		<category><![CDATA[merge]]></category>
		<category><![CDATA[reliability]]></category>
		<category><![CDATA[retries]]></category>
		<category><![CDATA[timeouts]]></category>
		<guid isPermaLink="false">https://qilin.cloud/?p=3688</guid>

					<description><![CDATA[<p>June’s focus: making resilience explicit. Merge policies (all/any/required), structured timeouts, retries, and continue/stop behavior—so pipelines degrade gracefully instead of collapsing.</p>
<p>The post <a rel="nofollow" href="https://qilin.cloud/merge-timeouts-retries-reliability-patterns/">Merge, Timeouts, Retries: Reliability Patterns for Composable Pipelines</a> appeared first on <a rel="nofollow" href="https://qilin.cloud">Qilin.Cloud</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><div class="et_pb_section et_pb_section_2 et_section_regular" >
				
				
				
				
				
				
				<div class="et_pb_row et_pb_row_16">
				<div class="et_pb_column et_pb_column_4_4 et_pb_column_16  et_pb_css_mix_blend_mode_passthrough et-last-child">
				
				
				
				
				<div class="et_pb_module et_pb_text et_pb_text_4  et_pb_text_align_left et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_text_inner"><p>Building a pipeline is easy.</p>
<p>Building a pipeline that behaves sensibly when the real world misbehaves… that’s where the craft lives.</p>
<p>External APIs time out. <br />One branch finishes fast, another crawls. <br />A connector returns a 500 for 3 minutes and then pretends nothing happened.</p>
<p>If you’ve lived through this, you know the traditional solutions:</p>
<ul>
<li>“just retry”</li>
<li>“just add a timeout”</li>
<li>“just wait for the other branch”</li>
<li>“just make it idempotent”</li>
</ul>
<p>All true, all vague.</p>
<p>June’s focus has been making those survival instincts <strong>explicit configuration</strong> inside Qilin.Cloud &#8211; especially around <strong>merging branches</strong> and handling errors without turning your pipeline into a fragile Jenga tower.</p></div>
			</div>
			</div>
				
				
				
				
			</div><div class="et_pb_row et_pb_row_17">
				<div class="et_pb_column et_pb_column_4_4 et_pb_column_17  et_pb_css_mix_blend_mode_passthrough et-last-child">
				
				
				
				
				<div class="et_pb_module pac_divi_table_of_contents pac_divi_table_of_contents_2">
				
				
				
				
				
				
				<div class="et_pb_module_inner">
					
        <div class="pac_dtoc_main_container"
        data-allow_collapse_minimize="on"
        data-allow_collapse_minimize_tablet="on"
        data-allow_collapse_minimize_phone="on"
        data-ss="2000"
        data-sah="100"
        data-collapse_when_sticky="off"
        data-collapse_when_sticky_tablet="off"
        data-collapse_when_sticky_phone="off"
        data-skh="off"
        data-mtocai="off"
        data-mtocai_tablet="off"
        data-mtocai_phone="off"
        data-alh="off"
        data-ds="closed"
        data-dst="closed"
        data-dsp="closed">
            <div class="pac_dtoc_title_area click_on click_tablet_on click_phone_on">
                <div role="heading" aria-level="2" id="pac_dtocm_title" class="pac_dtoc_title">Table of Contents</div>
                
                <div class="pac_dtoc_icon_responsive">
                    <div class="pac_dtoc_opened_icon">2</div>
                    <div class="pac_dtoc_closed_icon">3</div>
                </div>
                
            </div>
            <div role="navigation" aria-labelledby="pac_dtocm_title" class="pac_dtoc_body_area inside">
                
                <div class='divi_table_of_contents' role="tree" ><ul class="pac_dtoc_heading_level_1" role="group" ><li class="pac_dtoc_li_heading_level_1" role="treeitem" ><div role="presentation" ><span data-href='#pac_remove_first_heading' data-hl='1'></span><a href='#pac_remove_first_heading' id='pac_remove_first_heading_toc_headding'>FirstHeading</a></div></li><ul class="pac_dtoc_heading_level_2" role="group" ><li class="pac_dtoc_li_heading_level_2" role="treeitem" ><div role="presentation" ><span data-href='#MergeProcessorwhereparallelismmeetsreality' data-hl='2'></span><a href='#MergeProcessorwhereparallelismmeetsreality' id='MergeProcessorwhereparallelismmeetsreality_toc_headding'>Merge Processor: where parallelism meets reality</a></div></li><li class="pac_dtoc_li_heading_level_2" role="treeitem" ><div role="presentation" ><span data-href='#Threemergetimeoutpolicieschooseyourphilosophy' data-hl='2'></span><a href='#Threemergetimeoutpolicieschooseyourphilosophy' id='Threemergetimeoutpolicieschooseyourphilosophy_toc_headding'>Three merge timeout policies (choose your philosophy)</a></div></li><ul class="pac_dtoc_heading_level_3" role="group" ><li class="pac_dtoc_li_heading_level_3" role="treeitem" ><div role="presentation" ><span data-href='#1Waitforallinputprocessorsdefault' data-hl='3'></span><a href='#1Waitforallinputprocessorsdefault' id='1Waitforallinputprocessorsdefault_toc_headding'>1) Wait for all input processors (default)</a></div></li><li class="pac_dtoc_li_heading_level_3" role="treeitem" ><div role="presentation" ><span data-href='#2Waitforanyinputprocessor' data-hl='3'></span><a href='#2Waitforanyinputprocessor' id='2Waitforanyinputprocessor_toc_headding'>2) Wait for any input processor</a></div></li><li class="pac_dtoc_li_heading_level_3" role="treeitem" ><div role="presentation" ><span data-href='#3Waitforrequiredinputprocessors' data-hl='3'></span><a href='#3Waitforrequiredinputprocessors' id='3Waitforrequiredinputprocessors_toc_headding'>3) Wait for required input processors</a></div></li></ul><li class="pac_dtoc_li_heading_level_2" role="treeitem" ><div role="presentation" ><span data-href='#Timeoutsretriesandcontinueanyway' data-hl='2'></span><a href='#Timeoutsretriesandcontinueanyway' id='Timeoutsretriesandcontinueanyway_toc_headding'>Timeouts, retries, and “continue anyway”</a></div></li><li class="pac_dtoc_li_heading_level_2" role="treeitem" ><div role="presentation" ><span data-href='#Arealscenarioenrichingcatalogdatafromthreesources' data-hl='2'></span><a href='#Arealscenarioenrichingcatalogdatafromthreesources' id='Arealscenarioenrichingcatalogdatafromthreesources_toc_headding'>A real scenario: enriching catalog data from three sources</a></div></li><li class="pac_dtoc_li_heading_level_2" role="treeitem" ><div role="presentation" ><span data-href='#Filteringandenrichmentasfirstclassprocessors' data-hl='2'></span><a href='#Filteringandenrichmentasfirstclassprocessors' id='Filteringandenrichmentasfirstclassprocessors_toc_headding'>Filtering and enrichment as first-class processors</a></div></li><li class="pac_dtoc_li_heading_level_2" role="treeitem" ><div role="presentation" ><span data-href='#Whobenefits' data-hl='2'></span><a href='#Whobenefits' id='Whobenefits_toc_headding'>Who benefits?</a></div></li><ul class="pac_dtoc_heading_level_3" role="group" ><li class="pac_dtoc_li_heading_level_3" role="treeitem" ><div role="presentation" ><span data-href='#Developers' data-hl='3'></span><a href='#Developers' id='Developers_toc_headding'>Developers</a></div></li><li class="pac_dtoc_li_heading_level_3" role="treeitem" ><div role="presentation" ><span data-href='#Merchantsagencies' data-hl='3'></span><a href='#Merchantsagencies' id='Merchantsagencies_toc_headding'>Merchants &amp; agencies</a></div></li><li class="pac_dtoc_li_heading_level_3" role="treeitem" ><div role="presentation" ><span data-href='#Investors' data-hl='3'></span><a href='#Investors' id='Investors_toc_headding'>Investors</a></div></li></ul><li class="pac_dtoc_li_heading_level_2" role="treeitem" ><div role="presentation" ><span data-href='#Whatsnext' data-hl='2'></span><a href='#Whatsnext' id='Whatsnext_toc_headding'>What’s next</a></div></li><li class="pac_dtoc_li_heading_level_2" role="treeitem" ><div role="presentation" ><span data-href='#ReliabilityisnotmagicItspolicies' data-hl='2'></span><a href='#ReliabilityisnotmagicItspolicies' id='ReliabilityisnotmagicItspolicies_toc_headding'>Reliability is not magic. It’s policies.</a></div></li></ul></div>
            </div>
        </div>
        
				</div>
			</div>
			</div>
				
				
				
				
			</div><div class="et_pb_row et_pb_row_22">
				<div class="et_pb_column et_pb_column_4_4 et_pb_column_22  et_pb_css_mix_blend_mode_passthrough et-last-child">
				
				
				
				
				<div class="et_pb_module et_pb_blurb et_pb_blurb_38  et_pb_text_align_left  et_pb_blurb_position_top et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_blurb_content">
					
					<div class="et_pb_blurb_container">
						<h2 class="et_pb_module_header"><span>Merge Processor: where parallelism meets reality</span></h2>
						<div class="et_pb_blurb_description"><p>In a composable pipeline, you often run things in parallel:</p>
<ul>
<li>fetch price from system A</li>
<li>fetch description from system B</li>
<li>fetch stock from system C</li>
</ul>
<p>Eventually, you need to bring results back together.</p>
<p>That’s what the <strong>Merge Processor</strong> does.</p>
<p>But the tricky part is: <em>how long do you wait, and what do you do when not everything arrives?</em></p>
<p>So Qilin supports different merge policies.</p></div>
					</div>
				</div>
			</div>
			</div>
				
				
				
				
			</div><div class="et_pb_row et_pb_row_23">
				<div class="et_pb_column et_pb_column_4_4 et_pb_column_23  et_pb_css_mix_blend_mode_passthrough et-last-child">
				
				
				
				
				<div class="et_pb_module et_pb_blurb et_pb_blurb_39  et_pb_text_align_left  et_pb_blurb_position_top et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_blurb_content">
					
					<div class="et_pb_blurb_container">
						<h2 class="et_pb_module_header"><span>Three merge timeout policies (choose your philosophy)</span></h2>
						<div class="et_pb_blurb_description"><h3>1) Wait for all input processors (default)</h3>
<p>This is the “strict correctness” mode:</p>
<ul>
<li>Merge waits until <strong>all parent processors finish</strong></li>
<li>No timeout policy</li>
<li>Best when every input is required for a valid result</li>
</ul>
<p>Use this when incomplete data would be worse than delayed data.</p>
<h3>2) Wait for any input processor</h3>
<p>This is the “fast enough” mode:</p>
<ul>
<li>Merge starts a timeout countdown once <strong>any</strong> input finishes</li>
<li>When the timeout ends, merge proceeds with whatever results arrived</li>
</ul>
<p>Use this when you value speed and partial results are acceptable.</p>
<h3>3) Wait for required input processors</h3>
<p>This is the “hybrid” mode:</p>
<ul>
<li>define a list of required parents</li>
<li>wait for those to complete</li>
<li>start a timeout countdown afterward</li>
<li>proceed even if non-required inputs didn’t arrive</li>
</ul>
<p>Use this when some inputs are critical and others are optional enhancements.</p></div>
					</div>
				</div>
			</div><div class="et_pb_module et_pb_blurb et_pb_blurb_40  et_pb_text_align_left  et_pb_blurb_position_top et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_blurb_content">
					
					<div class="et_pb_blurb_container">
						<h2 class="et_pb_module_header"><span>Timeouts, retries, and “continue anyway”</span></h2>
						<div class="et_pb_blurb_description"><p>A timeout is not always a failure. Sometimes it’s just a signal.</p>
<p>So processors can be configured with:</p>
<ul>
<li><strong>TimeoutConfig</strong> (how long is “too long”)</li>
<li><strong>RetryConfig</strong> (how many times to retry and how long to wait between tries)</li>
<li><strong>OnErrorBehavior</strong> (continue vs stop)</li>
</ul>
<p>A simple retry policy looks like:</p>
<pre>"retryConfig": {
  "maximumRetries": 3,
  "retryAfterInSeconds": 3
}</pre>
<p>This gives you structured resilience without rewriting your own scheduler logic.</p></div>
					</div>
				</div>
			</div><div class="et_pb_module et_pb_blurb et_pb_blurb_41  et_pb_text_align_left  et_pb_blurb_position_top et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_blurb_content">
					
					<div class="et_pb_blurb_container">
						<h2 class="et_pb_module_header"><span>A real scenario: enriching catalog data from three sources</span></h2>
						<div class="et_pb_blurb_description"><p>Let’s say you enrich products using:</p>
<ul>
<li>ERP (core master data) → required</li>
<li>PIM (marketing text) → optional</li>
<li>Pricing service (dynamic pricing) → required</li>
</ul>
<p>A “required inputs” merge policy lets you:</p>
<ul>
<li>wait for ERP + pricing</li>
<li>proceed even if PIM is slow or unavailable</li>
<li>still produce a usable product update</li>
</ul>
<p>That’s a pipeline that keeps the business running without silently dropping correctness.</p></div>
					</div>
				</div>
			</div><div class="et_pb_module et_pb_accordion et_pb_accordion_5">
				
				
				
				
				<div class="et_pb_toggle et_pb_module et_pb_accordion_item et_pb_accordion_item_5  et_pb_toggle_open">
				
				
				
				
				<h5 class="et_pb_toggle_title"></h5>
				<div class="et_pb_toggle_content clearfix">We invite you to share your experiences and lessons learned with Qilin.Cloud’s innovative technology platform for composable e-commerce. Your story can inspire others and help the whole community to improve.</p>
<p>&nbsp;</p>
<h4><strong>Share your Qilin.Cloud Success Story</strong><br />
<span> </span></h4>
<div class="et_pb_button_module_wrapper et_pb_button_0_wrapper  et_pb_module "><a class="et_pb_button et_pb_button_0 et_pb_bg_layout_light" href="https://qilin.cloud/share-your-story/">Your Journey</a></div></div>
			</div>
			</div><div class="et_pb_module et_pb_blurb et_pb_blurb_42  et_pb_text_align_left  et_pb_blurb_position_top et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_blurb_content">
					
					<div class="et_pb_blurb_container">
						<h2 class="et_pb_module_header"><span>Filtering and enrichment as first-class processors</span></h2>
						<div class="et_pb_blurb_description"><p>Alongside merge reliability, we’ve also been expanding processors that work directly with object content:</p>
<ul>
<li>content filtering based on reusable predicate logic</li>
<li>content enrichment designed to combine or augment fields</li>
</ul>
<p>The long-term goal: keep transformations inside the pipeline, where they can be tracked, tested, and maintained.</p></div>
					</div>
				</div>
			</div><div class="et_pb_module et_pb_blurb et_pb_blurb_43  et_pb_text_align_left  et_pb_blurb_position_top et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_blurb_content">
					
					<div class="et_pb_blurb_container">
						<h2 class="et_pb_module_header"><span>Who benefits?</span></h2>
						<div class="et_pb_blurb_description"><h3>Developers</h3>
<ul>
<li>clear semantics instead of “mystery retries”</li>
<li>consistent timeout and retry behavior across processors</li>
<li>less custom glue code for parallel fan-out / fan-in patterns</li>
</ul>
<h3>Merchants &amp; agencies</h3>
<ul>
<li>fewer brittle syncs that collapse when one dependency hiccups</li>
<li>pipelines that degrade gracefully under partial failure</li>
<li>easier troubleshooting because behavior is explicit, not implied</li>
</ul>
<h3>Investors</h3>
<p>Reliability features reduce operational cost and support load. They’re not just technical niceties &#8211; they’re economic multipliers.</p></div>
					</div>
				</div>
			</div><div class="et_pb_module et_pb_blurb et_pb_blurb_44  et_pb_text_align_left  et_pb_blurb_position_top et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_blurb_content">
					
					<div class="et_pb_blurb_container">
						<h2 class="et_pb_module_header"><span>What’s next</span></h2>
						<div class="et_pb_blurb_description"><p>Once you can merge and retry reliably, you can start making a new trade:</p>
<p><strong>batching vs real-time.</strong></p>
<p>July will introduce more around queue-based buffering &#8211; because sometimes the smartest pipeline isn’t the fastest one, it’s the one that ships in stable, cost-efficient chunks.</p></div>
					</div>
				</div>
			</div><div class="et_pb_module et_pb_blurb et_pb_blurb_45  et_pb_text_align_left  et_pb_blurb_position_top et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_blurb_content">
					
					<div class="et_pb_blurb_container">
						<h2 class="et_pb_module_header"><span>Reliability is not magic. It’s policies.</span></h2>
						<div class="et_pb_blurb_description"><p>The “old way” taught us the patterns.</p>
<p>Qilin.Cloud is turning those patterns into configurable primitives &#8211; so your pipelines can behave like experienced engineers wrote them… even when nobody is awake at 03:00 AM.</p></div>
					</div>
				</div>
			</div>
			</div>
				
				
				
				
			</div>
				
				
			</div></p>
<p>The post <a rel="nofollow" href="https://qilin.cloud/merge-timeouts-retries-reliability-patterns/">Merge, Timeouts, Retries: Reliability Patterns for Composable Pipelines</a> appeared first on <a rel="nofollow" href="https://qilin.cloud">Qilin.Cloud</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Cache Miss Attack</title>
		<link>https://qilin.cloud/cache-miss-attack/</link>
					<comments>https://qilin.cloud/cache-miss-attack/#comments</comments>
		
		<dc:creator><![CDATA[Tuyen Nguyen]]></dc:creator>
		<pubDate>Sat, 15 Jul 2023 11:07:11 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://qilin.cloud/?p=738</guid>

					<description><![CDATA[<p>Caching is awesome but it doesn’t come without a cost, just like many things in life.</p>
<p>One of the issues is 𝐂𝐚𝐜𝐡𝐞 𝐌𝐢𝐬𝐬 𝐀𝐭𝐭𝐚𝐜𝐤. It refers to the scenario where data to fetch doesn't exist in the database and the data isn’t cached either.</p>
<p>The post <a rel="nofollow" href="https://qilin.cloud/cache-miss-attack/">Cache Miss Attack</a> appeared first on <a rel="nofollow" href="https://qilin.cloud">Qilin.Cloud</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><div class="et_pb_section et_pb_section_3 et_section_regular" >
				
				
				
				
				
				
				<div class="et_pb_row et_pb_row_24">
				<div class="et_pb_column et_pb_column_4_4 et_pb_column_24  et_pb_css_mix_blend_mode_passthrough et-last-child">
				
				
				
				
				<div class="et_pb_module et_pb_image et_pb_image_0">
				
				
				
				
				<a href="https://qilin.cloud/wp-content/uploads/2023/08/blog5-1.jpg" class="et_pb_lightbox_image" title=""><span class="et_pb_image_wrap "><img fetchpriority="high" decoding="async" width="960" height="489" src="https://qilin.cloud/wp-content/uploads/2023/08/blog5-1.jpg" alt="blog5 1" title="blog5-1" srcset="https://qilin.cloud/wp-content/uploads/2023/08/blog5-1.jpg 960w, https://qilin.cloud/wp-content/uploads/2023/08/blog5-1-480x245.jpg 480w" sizes="(min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) 960px, 100vw" class="wp-image-748"></span></a>
			</div><div class="et_pb_module et_pb_text et_pb_text_6  et_pb_text_align_left et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_text_inner"><p>B<span>efore understanding about Cache Miss Attack, let’s talk a little about </span><strong class="li ew">Cache</strong><span>.</span></p></div>
			</div><div class="et_pb_module et_pb_text et_pb_text_7  et_pb_text_align_left et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_text_inner"><h2 id="f2ad" class="mn mo ev be mp mq mr ms mt mu mv mw mx lr my mz na lv nb nc nd lz ne nf ng nh bj" data-selectable-paragraph="">What exactly is Cache?</h2>
<ul class="">
<li id="c058" class="lg lh ev li b lj ni ll lm ln nj lp lq nk nl lt lu nm nn lx ly no np mb mc md nq nr ns bj" data-selectable-paragraph="">A cache (pronounced “<strong class="li ew">cash</strong>”) is a hardware or software component used in computer systems to<span> </span><em class="nt">store frequently accessed data or instructions</em>, making it quickly accessible to the CPU or other processing units.</li>
<li id="7f6b" class="lg lh ev li b lj nu ll lm ln nv lp lq nk nw lt lu nm nx lx ly no ny mb mc md nq nr ns bj" data-selectable-paragraph="">The primary purpose of a cache is to<span> </span><em class="nt">reduce the time it takes to retrieve data from the main memory (RAM) or storage devices</em>, as accessing data from these slower sources can be relatively time-consuming compared to accessing data from a cache.</li>
</ul></div>
			</div><div class="et_pb_module et_pb_text et_pb_text_8  et_pb_text_align_left et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_text_inner"><h2 id="7d3e" class="mn mo ev be mp mq mr ms mt mu mv mw mx lr my mz na lv nb nc nd lz ne nf ng nh bj" data-selectable-paragraph="">Locality of Reference</h2>
<ul class="">
<li id="5a72" class="lg lh ev li b lj ni ll lm ln nj lp lq nk nl lt lu nm nn lx ly no np mb mc md nq nr ns bj" data-selectable-paragraph="">Caches work on the principle of exploiting the<span> </span><strong class="li ew"><em class="nt">locality of reference</em></strong><span> </span>exhibited by most programs and applications.</li>
<li id="7e90" class="lg lh ev li b lj nu ll lm ln nv lp lq nk nw lt lu nm nx lx ly no ny mb mc md nq nr ns bj" data-selectable-paragraph=""><strong class="li ew">Locality of reference</strong><span> </span>refers to the tendency of programs to access a relatively small portion of their memory space frequently and repeatedly for a short period of time.</li>
</ul>
<p id="b34d" class="pw-post-body-paragraph lg lh ev li b lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz ma mb mc md eo bj" data-selectable-paragraph="">There are two common types of caches:</p></div>
			</div><div class="et_pb_module et_pb_text et_pb_text_9  et_pb_text_align_left et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_text_inner"><ol class="">
<li id="d68f" data-selectable-paragraph=""><strong class="li ew">CPU Cache:</strong><br />
&emsp;→ The CPU cache is a<span> </span><strong class="li ew"><em class="nt">small, high-speed memory</em></strong><span> </span>integrated into the CPU itself or located very close to it.<br />
&emsp;→ It stores copies of<span> </span><em class="nt">frequently accessed data and instructions</em><span> </span>from the main memory.<br />
&emsp;→ When the CPU needs to read or write data, it first checks the cache. If the data is present in the cache (cache hit), it can be retrieved or modified much faster than fetching it from the main memory (cache miss).<br />
&emsp;→ CPU caches typically have multiple levels, such as<span> </span><strong class="li ew">L1, L2, and L3</strong><span> </span>caches, each with increasing size and farther from the CPU cores.</p>
</li>
<li id="8acb" data-selectable-paragraph=""><strong class="li ew">Disk Cache:</strong><br />
&emsp;→ It is a software-based cache used to accelerate data access from slower storage devices like<span> </span><strong class="li ew">hard disk drives</strong><span> </span>(HDDs) or<span> </span><strong class="li ew">solid-state drives</strong><span> </span>(SSDs).<br />
&emsp;→ It temporarily stores frequently read data from the disk in a faster memory, such as RAM or SSD, to reduce the time required to access that data again.<br />
&emsp;→ It helps improve the overall system performance by reducing the bottleneck caused by slower storage devices.</li>
</ol></div>
			</div><div class="et_pb_module et_pb_text et_pb_text_10  et_pb_text_align_left et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_text_inner"><h2 id="8f31" class="mn mo ev be mp mq mr ms mt mu mv mw mx lr my mz na lv nb nc nd lz ne nf ng nh bj" data-selectable-paragraph="">What is a Cache Hit?</h2>
<ul class="">
<li id="07ff" class="lg lh ev li b lj ni ll lm ln nj lp lq nk nl lt lu nm nn lx ly no np mb mc md nq nr ns bj" data-selectable-paragraph="">A cache hit occurs<span> </span><strong class="li ew">when the data or instruction requested by a processor is found in the cache memory</strong><span> </span>during a memory access operation.</li>
<li id="a965" class="lg lh ev li b lj nu ll lm ln nv lp lq nk nw lt lu nm nx lx ly no ny mb mc md nq nr ns bj" data-selectable-paragraph="">In other words, it means that<span> </span><em class="nt">the processor has successfully located the required information in the cache</em><span> </span>without the need to access the slower main memory or external storage devices.</li>
</ul></div>
			</div><div class="et_pb_module et_pb_text et_pb_text_11  et_pb_text_align_left et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_text_inner"><h2 id="e506" class="mn mo ev be mp mq mr ms mt mu mv mw mx lr my mz na lv nb nc nd lz ne nf ng nh bj" data-selectable-paragraph="">What is a Cache Miss?</h2>
<ul class="">
<li id="e36a" class="lg lh ev li b lj ni ll lm ln nj lp lq nk nl lt lu nm nn lx ly no np mb mc md nq nr ns bj" data-selectable-paragraph="">A cache miss occurs<span> </span><strong class="li ew">when the data or instruction requested by a processor is not found in the cache</strong><span> </span>during a memory access operation.</li>
<li id="8812" class="lg lh ev li b lj nu ll lm ln nv lp lq nk nw lt lu nm nx lx ly no ny mb mc md nq nr ns bj" data-selectable-paragraph="">In other words, it means that the processor attempted to access data that was not already stored in the cache,<span> </span><em class="nt">requiring the CPU to fetch the data from the slower main memory or external storage devices</em>.</li>
</ul></div>
			</div><div class="et_pb_module et_pb_text et_pb_text_12  et_pb_text_align_left et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_text_inner"><h2 id="607b" class="mn mo ev be mp mq mr ms mt mu mv mw mx lr my mz na lv nb nc nd lz ne nf ng nh bj" data-selectable-paragraph="">What is a “Cache Miss Attack”?</h2>
<p id="47e1" class="pw-post-body-paragraph lg lh ev li b lj ni ll lm ln nj lp lq lr nl lt lu lv nn lx ly lz np mb mc md eo bj" data-selectable-paragraph="">Let’s consider a scenario where a user is trying to access some data from an application and the<span> </span><strong class="li ew">data to be fetched doesn’t exist in the database and the data isn’t present in the cache either.</strong></p></div>
			</div><div class="et_pb_module et_pb_image et_pb_image_1">
				
				
				
				
				<a href="https://qilin.cloud/wp-content/uploads/2023/08/blog5-2.jpg" class="et_pb_lightbox_image" title=""><span class="et_pb_image_wrap "><img decoding="async" width="1104" height="1164" src="https://qilin.cloud/wp-content/uploads/2023/08/blog5-2.jpg" alt="blog5 2" title="blog5-2" srcset="https://qilin.cloud/wp-content/uploads/2023/08/blog5-2.jpg 1104w, https://qilin.cloud/wp-content/uploads/2023/08/blog5-2-980x1033.jpg 980w, https://qilin.cloud/wp-content/uploads/2023/08/blog5-2-480x506.jpg 480w" sizes="(min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1104px, 100vw" class="wp-image-749"></span></a>
			</div><div class="et_pb_module et_pb_text et_pb_text_13  et_pb_text_align_left et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_text_inner"><h2>So, what’s going to happen in this case?</h2>
<ul class="">
<li id="714e" class="lg lh ev li b lj lk ll lm ln lo lp lq nk ls lt lu nm lw lx ly no ma mb mc md nq nr ns bj" data-selectable-paragraph="">All the user requests will hit the database eventually, defeating the purpose of using a cache.</li>
<li id="68b4" class="lg lh ev li b lj nu ll lm ln nv lp lq nk nw lt lu nm nx lx ly no ny mb mc md nq nr ns bj" data-selectable-paragraph="">A malicious user submits some queries, is able to understand the pattern when the cache is being missed and then fires a lot of such queries, thus overloading the database.</li>
</ul></div>
			</div><div class="et_pb_module et_pb_text et_pb_text_14  et_pb_text_align_left et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_text_inner"><h2 id="f395" class="mn mo ev be mp mq mr ms mt mu mv mw mx lr my mz na lv nb nc nd lz ne nf ng nh bj" data-selectable-paragraph="">How can it be avoided?</h2>
<ul class="">
<li id="652c" class="lg lh ev li b lj ni ll lm ln nj lp lq nk nl lt lu nm nn lx ly no np mb mc md nq nr ns bj" data-selectable-paragraph="">We can design the APIs such that the users won’t be able to figure out of their requests are a Cache-Hit or a Cache-Miss.</li>
<li id="5fce" class="lg lh ev li b lj nu ll lm ln nv lp lq nk nw lt lu nm nx lx ly no ny mb mc md nq nr ns bj" data-selectable-paragraph="">If we have cache keys with null values, we should set a<span> </span><strong class="li ew">Short Time-To-Live (TTL)</strong><span> </span>for such keys.</li>
<li id="f96f" class="lg lh ev li b lj nu ll lm ln nv lp lq nk nw lt lu nm nx lx ly no ny mb mc md nq nr ns bj" data-selectable-paragraph="">Use a<span> </span><strong class="li ew">Web Application Firewall (WAF)</strong><span> </span>to detect and block malicious requests.</li>
<li id="1412" class="lg lh ev li b lj nu ll lm ln nv lp lq nk nw lt lu nm nx lx ly no ny mb mc md nq nr ns bj" data-selectable-paragraph=""><strong class="li ew">Cache the non-existent keys</strong>, so that the next time database won’t be hit because key can be found in the cache. However, this should be done with caution as<span> </span><em class="nt">attacker can inject a malicious payload</em><span> </span>in the GET request, and the response is cached.</li>
<li id="39f3" class="lg lh ev li b lj nu ll lm ln nv lp lq nk nw lt lu nm nx lx ly no ny mb mc md nq nr ns bj" data-selectable-paragraph=""><strong class="li ew">Use Bloom Filter:</strong><br />→ It is a<span> </span><em class="nt">space-efficient probabilistic data structure</em><span> </span>used to test whether an element is a member of a set.<br />→ It can be used to check<span> </span><em class="nt">if a key exists in a set</em>, such as a cache, without actually retrieving the key.<br />→ This can<span> </span><em class="nt">prevent cache miss attacks by making it difficult for an attacker to determine whether a specific key is in the cache</em>.<br />→ Bloom filters work by hashing the key and setting the corresponding bits in a bit array.<br />→ When checking if a key exists, the same hash function is applied to the key, and the corresponding bits in the bit array are checked. If all the bits are set, the key is probably in the set, but there is a small chance of a false positive.<br />→ If the key exists,<span> </span><em class="nt">the request first goes to the cache</em><span> </span>and then queries the database if needed.<br />→ If the key does not exist in the data set, it means the key is not present in the cache or the database.</li>
</ul></div>
			</div><div class="et_pb_module et_pb_text et_pb_text_15  et_pb_text_align_left et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_text_inner"><h2 id="be24" class="mn mo ev be mp mq mr ms mt mu mv mw mx lr my mz na lv nb nc nd lz ne nf ng nh bj" data-selectable-paragraph="">Conclusion</h2>
<p id="016e" class="pw-post-body-paragraph lg lh ev li b lj ni ll lm ln nj lp lq lr nl lt lu lv nn lx ly lz np mb mc md eo bj" data-selectable-paragraph="">It’s essential for software developers and system architects to be aware of the risks associated with cache miss attacks and<span> </span><strong class="li ew">design their systems with security in mind</strong>, especially when dealing with sensitive data. Additionally, operating system and hardware manufacturers continually work on mitigating these vulnerabilities and releasing patches to ensure the security of their systems.</p></div>
			</div>
			</div>
				
				
				
				
			</div>
				
				
			</div></p>
<p>The post <a rel="nofollow" href="https://qilin.cloud/cache-miss-attack/">Cache Miss Attack</a> appeared first on <a rel="nofollow" href="https://qilin.cloud">Qilin.Cloud</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://qilin.cloud/cache-miss-attack/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
	</channel>
</rss>
