<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[SubGame – Game Marketplace & News]]></title><description><![CDATA[SubGame is a secure and trusted marketplace for gamers to buy and sell accounts, items, and in-game currencies.
We share insights about the gaming industry and ]]></description><link>https://subgame.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Thu, 10 Sep 2026 10:50:00 GMT</lastBuildDate><atom:link href="https://subgame.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Handling Disputes in Digital Marketplaces: Designing a Fair, Evidence-Driven Resolution System]]></title><description><![CDATA[In any digital marketplace—especially those dealing with intangible assets like game accounts, items, or licenses—disputes are inevitable.
Even with strong escrow, authentication, and fraud-prevention mechanisms, edge cases still happen:

Partial del...]]></description><link>https://subgame.hashnode.dev/handling-disputes-in-digital-marketplaces-designing-a-fair-evidence-driven-resolution-system</link><guid isPermaLink="true">https://subgame.hashnode.dev/handling-disputes-in-digital-marketplaces-designing-a-fair-evidence-driven-resolution-system</guid><category><![CDATA[marketplace-architecture]]></category><category><![CDATA[trust-and-safety]]></category><category><![CDATA[System Design]]></category><category><![CDATA[Backend Engineering]]></category><category><![CDATA[Product Engineering]]></category><dc:creator><![CDATA[SubGame]]></dc:creator><pubDate>Fri, 26 Dec 2025 02:02:41 GMT</pubDate><content:encoded><![CDATA[<p>In any digital marketplace—especially those dealing with <strong>intangible assets like game accounts, items, or licenses</strong>—disputes are inevitable.</p>
<p>Even with strong escrow, authentication, and fraud-prevention mechanisms, edge cases still happen:</p>
<ul>
<li><p>Partial delivery</p>
</li>
<li><p>Account recovery attempts</p>
</li>
<li><p>Platform-side restrictions</p>
</li>
<li><p>Misunderstandings between buyer and seller</p>
</li>
</ul>
<p>The real differentiator is <strong>how disputes are handled</strong>, not whether they occur.</p>
<p>This article breaks down how to design a <strong>fair, scalable, and evidence-driven dispute resolution system</strong> for digital marketplaces, based on real-world patterns.</p>
<hr />
<h2 id="heading-1-why-disputes-are-a-system-design-problem">1. Why Disputes Are a System Design Problem</h2>
<p>Most teams initially treat disputes as a <strong>support problem</strong>.<br />In reality, disputes are a <strong>core system concern</strong> that impacts:</p>
<ul>
<li><p>Trust</p>
</li>
<li><p>Retention</p>
</li>
<li><p>Legal risk</p>
</li>
<li><p>Operational cost</p>
</li>
</ul>
<p>If your dispute flow is vague or inconsistent, users will:</p>
<ul>
<li><p>Avoid high-value transactions</p>
</li>
<li><p>Bypass escrow</p>
</li>
<li><p>Or churn permanently after one bad experience</p>
</li>
</ul>
<p>A good dispute system must be <strong>predictable, transparent, and auditable</strong>.</p>
<hr />
<h2 id="heading-2-defining-clear-dispute-states">2. Defining Clear Dispute States</h2>
<p>A common mistake is handling disputes as a single Boolean: <em>open</em> or <em>closed</em>.</p>
<p>In practice, you need a <strong>state machine</strong>, for example:</p>
<ul>
<li><p><code>opened</code></p>
</li>
<li><p><code>awaiting_evidence</code></p>
</li>
<li><p><code>under_review</code></p>
</li>
<li><p><code>request_more_info</code></p>
</li>
<li><p><code>resolved_buyer</code></p>
</li>
<li><p><code>resolved_seller</code></p>
</li>
<li><p><code>partial_refund</code></p>
</li>
<li><p><code>escalated</code></p>
</li>
</ul>
<p>Each state should:</p>
<ul>
<li><p>Have a strict transition rule</p>
</li>
<li><p>Be time-bound</p>
</li>
<li><p>Trigger specific notifications</p>
</li>
</ul>
<p>This prevents disputes from becoming “infinite conversations.”</p>
<hr />
<h2 id="heading-3-evidence-first-not-opinion-first">3. Evidence-First, Not Opinion-First</h2>
<p>Dispute resolution should be driven by <strong>verifiable evidence</strong>, not subjective explanations.</p>
<p>Design your system to accept structured evidence:</p>
<ul>
<li><p>Timestamped videos</p>
</li>
<li><p>Screenshots with metadata</p>
</li>
<li><p>System logs (login changes, email updates, IP shifts)</p>
</li>
<li><p>Transaction history snapshots</p>
</li>
</ul>
<p>Avoid free-text-only claims.<br />Instead, force users into <strong>evidence-backed assertions</strong>.</p>
<p>Example:</p>
<blockquote>
<p>“Account access lost” → requires login failure proof + timestamp</p>
</blockquote>
<hr />
<h2 id="heading-4-time-windows-matter-more-than-you-think">4. Time Windows Matter More Than You Think</h2>
<p>One of the most effective trust mechanisms is a <strong>defined protection window</strong>.</p>
<p>Example pattern:</p>
<ul>
<li><p>Buyer protection: 7–14 days</p>
</li>
<li><p>Seller liability: limited to that window</p>
</li>
<li><p>After expiry, disputes require a higher evidence threshold</p>
</li>
</ul>
<p>Timeboxing disputes:</p>
<ul>
<li><p>Reduces abuse</p>
</li>
<li><p>Encourages fast testing by buyers</p>
</li>
<li><p>Limits the indefinite responsibility for sellers</p>
</li>
</ul>
<p>From a system perspective, this is just <strong>TTL on dispute eligibility</strong>—but its impact on trust is huge.</p>
<hr />
<h2 id="heading-5-role-based-visibility-and-permissions">5. Role-Based Visibility and Permissions</h2>
<p>Not everyone should see everything.</p>
<p>A clean dispute system defines roles clearly:</p>
<ul>
<li><p>Buyer: upload evidence, respond</p>
</li>
<li><p>Seller: respond, submit counter-evidence</p>
</li>
<li><p>Moderator: read-only logs + decision authority</p>
</li>
<li><p>System: immutable event recorder</p>
</li>
</ul>
<p>Crucially:</p>
<ul>
<li><p>Evidence should be <strong>append-only</strong></p>
</li>
<li><p>Edits should be versioned</p>
</li>
<li><p>Decisions should reference specific evidence IDs</p>
</li>
</ul>
<p>This creates accountability and protects your moderation team.</p>
<hr />
<h2 id="heading-6-automation-without-losing-fairness">6. Automation Without Losing Fairness</h2>
<p>You should automate:</p>
<ul>
<li><p>Deadlines</p>
</li>
<li><p>Missing-response penalties</p>
</li>
<li><p>Evidence validation checks</p>
</li>
<li><p>State transitions</p>
</li>
</ul>
<p>But <strong>never automate final verdicts</strong> for high-value disputes.</p>
<p>Instead:</p>
<ul>
<li><p>Use automation to narrow outcomes</p>
</li>
<li><p>Flag anomalies</p>
</li>
<li><p>Reduce manual workload</p>
</li>
</ul>
<p>Think of automation as <strong>triage</strong>, not judgment.</p>
<hr />
<h2 id="heading-7-auditability-is-non-negotiable">7. Auditability Is Non-Negotiable</h2>
<p>Every dispute should be reconstructable after the fact.</p>
<p>That means:</p>
<ul>
<li><p>Immutable event logs</p>
</li>
<li><p>Clear timestamps</p>
</li>
<li><p>Stored decision rationales</p>
</li>
<li><p>Linked evidence</p>
</li>
</ul>
<p>This protects you against:</p>
<ul>
<li><p>User appeals</p>
</li>
<li><p>Legal inquiries</p>
</li>
<li><p>Internal moderation conflicts</p>
</li>
</ul>
<p>If you can’t explain <em>why</em> a dispute was resolved a certain way, the system is broken.</p>
<hr />
<h2 id="heading-8-designing-for-trust-not-just-resolution">8. Designing for Trust, Not Just Resolution</h2>
<p>A strong dispute system doesn’t just “solve problems” — it <strong>prevents future ones</strong>.</p>
<p>Well-designed systems:</p>
<ul>
<li><p>Educate users during disputes</p>
</li>
<li><p>Reveal risky behavior patterns</p>
</li>
<li><p>Improve listing rules and onboarding</p>
</li>
<li><p>Feed insights back into fraud prevention</p>
</li>
</ul>
<p>In mature marketplaces, disputes become <strong>a data source</strong>, not just a cost center.</p>
<hr />
<h2 id="heading-final-thoughts">Final Thoughts</h2>
<p>Disputes are unavoidable in <a target="_blank" href="https://subgame.ir/">digital marketplace</a>s dealing with virtual goods.<br />What separates amateur platforms from professional ones is <strong>structure, evidence, and fairness</strong>.</p>
<p>If users believe:</p>
<ul>
<li><p>The process is clear</p>
</li>
<li><p>Decisions are consistent</p>
</li>
<li><p>Evidence actually matters</p>
</li>
</ul>
<p>They will trust the platform—even when they lose a dispute.</p>
<p>And that trust is the hardest thing to build, and the easiest thing to lose</p>
]]></content:encoded></item><item><title><![CDATA[مقیاس‌پذیری ویژگی‌های بلادرنگ در مارکت‌پلیس‌‌های بازی]]></title><description><![CDATA[مقدمه:
برای ارائه عملکرد بلادرنگ پایدار و مقیاس‌پذیر در یک مارکت‌پلیس بازی به سه لایه نیاز دارید: ۱) گِیت‌وی وب‌سوکت/Realtime (اتصال کاربر)، ۲) لایه‌ی پیغام‌رسانی (pub/sub با تضمین تحویل مناسب)، ۳) لایه‌ی پردازش/ذخیره‌سازی (لاگ‌ها، تاریخچه چت، وضعیت ...]]></description><link>https://subgame.hashnode.dev/communicate-system-dar-marketplace-bazi</link><guid isPermaLink="true">https://subgame.hashnode.dev/communicate-system-dar-marketplace-bazi</guid><category><![CDATA[GameMarketplace]]></category><category><![CDATA[realtime]]></category><category><![CDATA[websockets]]></category><category><![CDATA[Redis]]></category><category><![CDATA[kafka]]></category><category><![CDATA[FastAPI]]></category><category><![CDATA[scalability]]></category><dc:creator><![CDATA[SubGame]]></dc:creator><pubDate>Tue, 04 Nov 2025 15:12:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1762268352669/7262b086-8151-421f-b859-a5881c27a4cc.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-mkdmh"><strong>مقدمه:</strong></h2>
<p>برای ارائه عملکرد بلادرنگ پایدار و مقیاس‌پذیر در یک <a target="_blank" href="https://subgame.ir/">مارکت‌پلیس بازی</a> به سه لایه نیاز دارید: ۱) گِیت‌وی وب‌سوکت/Realtime (اتصال کاربر)، ۲) لایه‌ی پیغام‌رسانی (pub/sub با تضمین تحویل مناسب)، ۳) لایه‌ی پردازش/ذخیره‌سازی (لاگ‌ها، تاریخچه چت، وضعیت سفارش). ترکیب Redis (pub/sub یا streams)، صف پیام (Kafka/RabbitMQ) برای تضمین و Elastic/DB برای لاگینگ معمول‌ترین انتخاب است. در ادامه معماری‌ها، trade-offها و نمونه‌کد FastAPI + Redis آورده شده است.</p>
<hr />
<h2 id="heading-chra-oizhgihai-bladrng-mhmand">چرا ویژگی‌های بلادرنگ مهم‌اند؟</h2>
<ul>
<li><p><strong>اعتماد و تجربه کاربری:</strong> پیام سریع، نوتیف واقعی و آپدیت سریع سفارش‌ها باعث افزایش نرخ تبدیل و کاهش اختلاف می‌شود.</p>
</li>
<li><p><strong>تعامل بیشتر:</strong> چت و نوتیف در لحظه یعنی کاربر بیشتر می‌ماند و احتمال معامله افزایش می‌یابد.</p>
</li>
<li><p><strong>انتقال وضعیت سفارش:</strong> وقتی وضعیت سفارش (پرداخت، تحویل، تأیید) بلادرنگ منتقل شود، فرایند escrow روان‌تر می‌شود.</p>
</li>
</ul>
<hr />
<h2 id="heading-asol-maamari-high-level">اصول معماری (High-level)</h2>
<ol>
<li><p><strong>WebSocket / Gateway layer</strong></p>
<ul>
<li><p>مسئول نگه داشتن اتصالات کاربر، احراز هویت اتصال و توزیع پیام به کلاینت‌ها.</p>
</li>
<li><p>می‌تواند با Load Balancer و sticky-session یا با token-based routing کار کند.</p>
</li>
</ul>
</li>
<li><p><strong>Message Bus / PubSub</strong></p>
<ul>
<li><p>Redis Pub/Sub یا Redis Streams برای ارسال فوری پیام‌ها بین سرورها.</p>
</li>
<li><p>Kafka یا RabbitMQ برای سناریوهای نیازمند پردازش با تضمین (at-least-once، replay).</p>
</li>
</ul>
</li>
<li><p><strong>Processing / Business Logic</strong></p>
<ul>
<li>Workerها پیام‌ها را پردازش، اعتبارسنجی و در صورت لزوم به DB یا سرویس ثالث می‌فرستند (مثلاً ارسال ایمیل یا push).</li>
</ul>
</li>
<li><p><strong>Persistence</strong></p>
<ul>
<li><p>PostgreSQL برای وضعیت سفارش و تراکنش‌ها.</p>
</li>
<li><p>ElasticSearch یا ClickHouse برای جستجوی پیام/لاگ و تحلیل.</p>
</li>
<li><p>Redis برای presence / cache و پیام‌های موقت.</p>
</li>
</ul>
</li>
<li><p><strong>Push Notifications (APNs/FCM)</strong></p>
<ul>
<li>برای کاربرهای آفلاین پیام از طریق FCM/APNs ارسال شود.</li>
</ul>
</li>
<li><p><strong>Observability &amp; SRE</strong></p>
<ul>
<li>Metrics (Prometheus), Traces (Jaeger), Logs (ELK) و alerting برای SLO و SLA.</li>
</ul>
</li>
</ol>
<hr />
<h2 id="heading-algohai-aamli-patterns-amp-trade-offs">الگوهای عملی (Patterns &amp; Trade-offs)</h2>
<h3 id="heading-a-sadh-o-sriaa-single-redis-pubsub-stateful-websocket-servers">A — ساده و سریع: Single Redis Pub/Sub + stateful websocket servers</h3>
<ul>
<li><p>مزایا: پیاده‌سازی سریع، کم‌هزینه.</p>
</li>
<li><p>معایب: هیچ تضمین تحویلی یا persistence؛ اگر سرور می‌افتد پیام از بین می‌رود. مناسب برای پیام‌های UI/non-critical.</p>
</li>
</ul>
<h3 id="heading-b-redis-streams-consumer-groups-recommended-middle">B — Redis Streams + consumer groups (recommended middle)</h3>
<ul>
<li><p>مزایا: replay، durability در سطح Redis، consumer group برای پردازش موازی.</p>
</li>
<li><p>معایب: نیاز به مانیتورینگ stream length و retention.</p>
</li>
</ul>
<h3 id="heading-c-kafka-durable-processors-enterprise-grade">C — Kafka + durable processors (enterprise grade)</h3>
<ul>
<li><p>مزایا: مقیاس‌پذیری بالا، retention و replay قوی، اکوسیستم پردازشی (ksql, stream).</p>
</li>
<li><p>معایب: پیچیدگی و هزینه بیشتر.</p>
</li>
</ul>
<h3 id="heading-presence-online-status">Presence / Online status</h3>
<ul>
<li>نگهداری presence در Redis (مثلاً key <code>presence:user:{id}</code> با TTL) و انتشار تغییر در کانال presence.</li>
</ul>
<h3 id="heading-rate-limiting-amp-anti-abuse">Rate limiting &amp; Anti-abuse</h3>
<ul>
<li>نرخ‌محدودیت به‌دو شکل: at-connection (per-socket) و per-user (global across sockets). از leaky-bucket یا token-bucket در Redis استفاده کن.</li>
</ul>
<hr />
<h2 id="heading-nmonh-grian-piam-sfarsh-order-update-flow">نمونه جریان پیام سفارش (Order update flow)</h2>
<ol>
<li><p>کاربر A عملیاتی انجام می‌دهد (مثلاً mark "delivered").</p>
</li>
<li><p>سرویس API وضعیت را در Postgres ذخیره می‌کند و یک event به Kafka/Redis stream منتشر می‌کند: <code>order.updated</code>.</p>
</li>
<li><p>workerها event را consume و به channel مربوطه publish می‌کنند (مثلاً <code>order:{order_id}:channel</code>).</p>
</li>
<li><p>gatewayهای وب‌سوکت که به آن channel مشترکند پیام را به کلاینت‌های متصل فوروارد می‌کنند.</p>
</li>
<li><p>اگر کاربر آفلاین باشد، worker فوروارد به push provider (FCM/APNs) را انجام می‌دهد.</p>
</li>
</ol>
<hr />
<h2 id="heading-nmonhkd-fastapi-websocket-redis-pubsub-paih-async">نمونه‌کد: FastAPI WebSocket + Redis Pub/Sub (پایه — async)</h2>
<blockquote>
<p>این snippet برای فهم جریان است. برای production مواردی مثل reconnect/backpressure و error handling باید کامل شود.</p>
</blockquote>
<pre><code class="lang-plaintext"># requirements: fastapi, uvicorn, aioredis, python-jose (برای JWT)
from fastapi import FastAPI, WebSocket, WebSocketDisconnect, Depends
import aioredis
import asyncio
import os
from jose import jwt

app = FastAPI()
REDIS_URL = os.getenv("REDIS_URL", "redis://localhost:6379")
redis = None

async def get_redis():
    global redis
    if not redis:
        redis = await aioredis.create_redis_pool(REDIS_URL)
    return redis

# Simple in-memory registry of connections per user (for demo)
CONNECTIONS = {}  # user_id -&gt; set of websockets

async def verify_token(token: str):
    # ساده‌شده: در عمل از public key / jwks استفاده کنید
    try:
        payload = jwt.decode(token, "secret-key", algorithms=["HS256"])
        return payload.get("sub")
    except Exception:
        return None

@app.on_event("startup")
async def startup():
    await get_redis()
    # spawn background listener
    asyncio.create_task(redis_listener())

async def redis_listener():
    r = await get_redis()
    pubsub = (await r.subscribe("orders", "chat"))  # کانال‌های نمونه
    channels = [c for c in pubsub]
    while True:
        for ch in channels:
            msg = await ch.get(encoding="utf-8")
            if msg:
                # msg expected format: "channel|user_id|payload"
                # مثال: "order:123|user:45|{\"type\":\"order.update\",...}"
                try:
                    target_channel, user_id, payload = msg.split("|", 2)
                except:
                    continue
                conns = CONNECTIONS.get(user_id, set())
                for ws in list(conns):
                    try:
                        await ws.send_text(payload)
                    except:
                        # cleanup broken connections
                        conns.remove(ws)

@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket, token: str = ""):
    await websocket.accept()
    user_id = await verify_token(token)
    if not user_id:
        await websocket.close(code=4001)
        return
    CONNECTIONS.setdefault(user_id, set()).add(websocket)
    try:
        while True:
            data = await websocket.receive_text()
            # پیام از کلاینت -&gt; منتشر کن در Redis تا سایر سرورها دریافت کنند
            r = await get_redis()
            # نمونه قالب: "chat|user:45|{\"text\":\"hello\"}"
            await r.publish("chat", f"chat|{user_id}|{data}")
    except WebSocketDisconnect:
        CONNECTIONS[user_id].remove(websocket)
</code></pre>
<p><strong>نکات:</strong></p>
<ul>
<li><p>این مثال برای demo است؛ در production از connection pool بیشتر، مدیریت خطا، محدودیت اندازه پیام و اعتبارسنجی پیام‌ها استفاده کنید.</p>
</li>
<li><p>برای مقیاس‌پذیری CONNECTIONS نباید در حافظه‌ی پروسس نگه داشته شود؛ باید هر گِیت‌وی فقط کانکشن‌های متصل خودش را مدیریت کند و پیام‌ها از طریق Redis/Kafka بین گِیت‌وی‌ها فوروارد شوند.</p>
</li>
</ul>
<hr />
<h2 id="heading-nkat-mhm-aamli-brai-production">نکات مهم عملی برای Production</h2>
<ol>
<li><p><strong>Sticky session یا token routing</strong></p>
<ul>
<li>اگر از stateful websocket servers استفاده می‌کنی، برای کاهش راندربک نیاز به sticky sessions (LB) یا یک 토큰 routing که کاربر را به سرور مشخصی وصل کند لازم است. گزینه‌ی بهتر: هر گِیت‌وی اتصال را نگه‌دارد و پیام‌ها را از pub/sub دریافت کند.</li>
</ul>
</li>
<li><p><strong>Backpressure و batching</strong></p>
<ul>
<li>از فشرده‌سازی (gzip) و batching پیام استفاده کن. برای کاربران با شبکه ضعیف پیام‌ها را با QoS پایین‌تر ارسال کن یا drop کن.</li>
</ul>
</li>
<li><p><strong>QoS و تضمین تحویل</strong></p>
<ul>
<li>برای پیام‌های حساس (مثلاً وضعیت مالی) از Kafka/Streams با acknowledgement استفاده کن. پیام‌های UI-only می‌توانند best-effort باشند.</li>
</ul>
</li>
<li><p><strong>Security</strong></p>
<ul>
<li>WebSocket باید TLS داشته باشد (wss). JWT باید کوتاه‌مدت و دارای claim مناسب باشد. از CORS/Origin checks استفاده کن، و limit rate برای جلوگیری از DoS.</li>
</ul>
</li>
<li><p><strong>Persistence و audit</strong></p>
<ul>
<li>هر رویداد مهم (order state change, dispute events) را لاگ و ذخیره کن تا در حل اختلاف به کار آید.</li>
</ul>
</li>
<li><p><strong>Monitoring</strong></p>
<ul>
<li>Metricهایی مثل connections, messages/sec, avg-latency, redis-stream-lag و consumer-lag باید پایش شوند.</li>
</ul>
</li>
</ol>
<hr />
<h2 id="heading-kpihaii-kh-baid-paish-knid">KPIهایی که باید پایش کنید</h2>
<ul>
<li><p>تعداد کانکشن همزمان (peak)</p>
</li>
<li><p>میانگین latency پیام (publish → delivery)</p>
</li>
<li><p>پیام‌های از دست‌رفته یا failed deliveries</p>
</li>
<li><p>طول صف/lag در Redis Streams یا Kafka</p>
</li>
<li><p>نرخ disconnect / reconnect برای کاربران</p>
</li>
<li><p>CPU/RAM بر گِیت‌وی‌ها و latency پاسخ</p>
</li>
</ul>
<hr />
<h2 id="heading-abzarha-o-sroishai-mrtbt-gzinhhai-sriaa">ابزارها و سرویس‌های مرتبط (گزینه‌های سریع)</h2>
<ul>
<li><p>Managed Realtime: Pusher, Ably, PubNub — سریع ولی هزینه بر.</p>
</li>
<li><p>Managed Kafka: Confluent Cloud یا AWS MSK.</p>
</li>
<li><p>Redis Enterprise (Streams + Streams Consumer Groups) برای durability بهتر.</p>
</li>
<li><p>NATS JetStream برای پیام‌رسانی سبک و سریع با ویژگی‌های persistence.</p>
</li>
</ul>
<hr />
<h2 id="heading-gmaabndi-aamli">جمع‌بندی عملی</h2>
<ul>
<li><p>اگر می‌خوای سریع راه بیندازی برای قابلیت‌های UI-like (چت ساده، نوتیف فید)، از <strong>Redis Pub/Sub</strong> + Websocket Gateway شروع کن.</p>
</li>
<li><p>اگر پیام‌ها مهم و قابلکلیدی هستند (تراکنشی)، از <strong>Kafka/Redis Streams + consumer groups + durability</strong> استفاده کن.</p>
</li>
<li><p>همیشه برای production: TLS، authentication، rate-limit، persistence و observability را پیاده کن.</p>
</li>
<li><p>تست بار (k6, locust) را از روز اول اجرا کن و SLO تعریف کن.</p>
</li>
</ul>
<p><a target="_blank" href="https://subgame.ir/blog">تیم تحریریه ساب‌گیم</a> ـــــ</p>
]]></content:encoded></item><item><title><![CDATA[Building Fast, Relevant Search & Discovery for Game Marketplaces]]></title><description><![CDATA[Introduction
A game marketplace lives or dies by discovery. If buyers can’t find the right PUBG account, the right CS2 skin, or the best WoW gold offer, no amount of escrow, UX polish, or marketing will help.
This article shows a practical, productio...]]></description><link>https://subgame.hashnode.dev/building-fast-relevant-search-and-discovery-for-game-marketplaces</link><guid isPermaLink="true">https://subgame.hashnode.dev/building-fast-relevant-search-and-discovery-for-game-marketplaces</guid><category><![CDATA[Game Marketplace]]></category><category><![CDATA[search]]></category><category><![CDATA[elasticsearch]]></category><category><![CDATA[full text search]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[FastAPI]]></category><category><![CDATA[relevance]]></category><category><![CDATA[backend]]></category><dc:creator><![CDATA[SubGame]]></dc:creator><pubDate>Fri, 17 Oct 2025 02:46:56 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>A game marketplace lives or dies by discovery. If buyers can’t <em>find</em> the right PUBG account, the right CS2 skin, or the best WoW gold offer, no amount of escrow, UX polish, or marketing will help.</p>
<p>This article shows a practical, production-ready approach for <strong>search and discovery</strong> in game marketplaces: how to design the indexing pipeline, choose storage (Elasticsearch vs Postgres), implement relevance scoring, add faceted filters &amp; autocomplete, and serve results efficiently to a Next.js front end and FastAPI backend.</p>
<hr />
<h2 id="heading-1-basic-requirements-what-search-must-deliver">1) Basic requirements (what search must deliver)</h2>
<p>For a listings marketplace, you usually need:</p>
<ul>
<li><p><strong>Low latency</strong> queries (&lt; 100–300ms typical) for autocomplete and results.</p>
</li>
<li><p><strong>Relevant ranking</strong> mixing text relevance, recency, price proximity, seller reputation, and conversion signals.</p>
</li>
<li><p><strong>Facets &amp; filters</strong> (game, platform, rarity, price range, verification).</p>
</li>
<li><p><strong>Autocomplete &amp; fuzzy matching</strong> (typos, abbreviations).</p>
</li>
<li><p><strong>Incremental indexing</strong> (new/updated listingsare visible fast).</p>
</li>
<li><p><strong>Analytics</strong> (query CTR, zero-result rate, conversions) to iterate on ranking.</p>
</li>
</ul>
<hr />
<h2 id="heading-2-storage-elasticsearch-vs-postgresql-full-text">2) Storage: Elasticsearch vs PostgreSQL full-text</h2>
<p><strong>Postgres full-text</strong> is attractive for simplicity and cost; it’s fine for small catalogs (&lt;100k active listings) and simple needs (basic text search + filters). Use <code>GIN</code> indexes and <code>ts_rank</code> for ranking.</p>
<p><strong>Elasticsearch (or OpenSearch)</strong> is the pragmatic choice once you need:</p>
<ul>
<li><p>near-real-time indexing,</p>
</li>
<li><p>advanced relevance tuning (BM25, custom scoring),</p>
</li>
<li><p>complex aggregations for facets,</p>
</li>
<li><p>fast autocomplete and fuzzy multi-field queries,</p>
</li>
<li><p>horizontal scaling for high QPS.</p>
</li>
</ul>
<p><strong>Rule of thumb:</strong> start with Postgres if light traffic and iterate. Move to ES when you need better relevance, scale, or aggregation performance.</p>
<hr />
<h2 id="heading-3-index-design-elasticsearch-example">3) Index design (Elasticsearch example)</h2>
<p>Design an index that stores both textual fields and numeric signals for scoring:</p>
<pre><code class="lang-plaintext">PUT /listings
{
  "mappings": {
    "properties": {
      "title": { "type": "text", "analyzer": "standard" },
      "game": { "type": "keyword" },
      "platform": { "type": "keyword" },
      "price": { "type": "float" },
      "created_at": { "type": "date" },
      "seller_reputation": { "type": "float" },
      "views": { "type": "integer" },
      "is_verified": { "type": "boolean" },
      "inventory_summary": { "type": "text" }
    }
  }
}
</code></pre>
<p>Store <strong>signals</strong> (views, completed_sales, dispute_rate) to feed into ranking.</p>
<hr />
<h2 id="heading-4-ranking-combine-relevance-business-signals">4) Ranking: combine relevance + business signals</h2>
<p>A high-converting search result balances text match with business objectives. A typical scoring formula:</p>
<pre><code class="lang-plaintext">POST /listings/_search
{
  "query": {
    "function_score": {
      "query": {
        "multi_match": {
          "query": "pubg level 80 awm",
          "fields": ["title^3","inventory_summary","game^2"]
        }
      },
      "field_value_factor": {
        "field": "seller_reputation",
        "factor": 1.2,
        "modifier": "sqrt"
      },
      "boost_mode": "sum",
      "score_mode": "sum",
      "functions": [
        { "gauss": { "created_at": { "origin": "now", "scale": "14d", "decay": 0.5 } } },
        { "field_value_factor": { "field": "views", "modifier": "log1p", "factor": 0.2 } }
      ]
    }
  }
}
</code></pre>
<p>Tune α–ε empirically using A/B tests and historical data.</p>
<hr />
<h2 id="heading-5-autocomplete-amp-fuzzy-matching">5) Autocomplete &amp; Fuzzy Matching</h2>
<ul>
<li><p>Use an edge-ngram analyzer for prefix autocomplete (<code>"search_as_you_type"</code> in ES 7+).</p>
</li>
<li><p>Add fuzzy matching for typos (<code>fuzziness: "AUTO"</code>) and synonyms (e.g., “cod” -&gt; “call of duty”).</p>
</li>
<li><p>Keep autocomplete lightweight: only search a few fields (title, game).</p>
</li>
</ul>
<p>Example query for suggestions:</p>
<pre><code class="lang-plaintext">GET /listings/_search
{
  "suggest": {
    "listing-suggest": {
      "prefix": "pubg le",
      "completion": {
        "field": "title.suggest",
        "size": 8
      }
    }
  }
}
</code></pre>
<hr />
<h2 id="heading-6-faceted-navigation-amp-counts">6) Faceted navigation &amp; counts</h2>
<p>Use aggregations to generate facet counts (game, rarity, platform). On high QPS systems, cache aggregations for common filters or compute counts are performed in a background job.</p>
<p>Be careful with expensive aggregations on large datasets — precompute popular facets or use rollups.</p>
<hr />
<h2 id="heading-7-incremental-indexing-amp-eventual-consistency">7) Incremental indexing &amp; eventual consistency</h2>
<ul>
<li><p>Index on create/update via a message queue (RabbitMQ/Kafka). This decouples user writes and search indexing and avoids input blocking.</p>
</li>
<li><p>Use a small buffer (seconds–minutes) for near-real-time. Provide UI messaging: “Results may take up to X seconds to appear.”</p>
</li>
<li><p>For critical flows (e.g., buyer searching for a just-posted listing after checkout), you can do a <strong>read-through</strong>: query DB as a fallback for recent entries.</p>
</li>
</ul>
<hr />
<h2 id="heading-8-serving-results-to-nextjs-fastapi">8) Serving results to Next.js + FastAPI</h2>
<p>Flow:</p>
<ol>
<li><p>Frontend (Next.js) calls API: <code>GET /search?q=...&amp;filters=...&amp;page=...</code>.</p>
</li>
<li><p>FastAPI acts as a thin proxy: validate params, enrich with user context (location, currency), then call ES.</p>
</li>
<li><p>FastAPI returns normalized results (IDs, highlights, price, seller badge).</p>
</li>
</ol>
<p>For SEO:</p>
<ul>
<li><p>Use SSR or ISR for category pages and top queries (Next.js getStaticProps / getServerSideProps) to let search engines index curated pages.</p>
</li>
<li><p>Individual listing pages should be fully SSR’d to support rich snippets.</p>
</li>
</ul>
<hr />
<h2 id="heading-9-performance-amp-caching">9) Performance &amp; caching</h2>
<ul>
<li><p>Cache top queries (Redis) for 10–60s TTL.</p>
</li>
<li><p>Use HTTP caching headers for repeated requests (with Vary headers for filters).</p>
</li>
<li><p>Monitor ES slow logs and shard hot spots. Use read replicas for query scaling.</p>
</li>
</ul>
<hr />
<h2 id="heading-10-analytics-amp-iterative-tuning">10) Analytics &amp; iterative tuning</h2>
<p>Track:</p>
<ul>
<li><p>Query CTR, zero-result rate, time-to-first-click, conversion rate per query.</p>
</li>
<li><p>Run controlled A/B tests for ranking changes.</p>
</li>
<li><p>Use logs to extract synonyms, long-tail phrasings, and failed queries to improve analyzers and synonyms.</p>
</li>
</ul>
<hr />
<h2 id="heading-conclusion-amp-next-steps">Conclusion &amp; next steps</h2>
<p>Search and discovery is a product problem as much as a technical one. Start by shipping a simple, fast system (Postgres or ES), measure real queries, then iterate your ranking using business signals. Key investments — autocomplete, faceted filters, incremental indexing, and analytics — pay off quickly in higher conversions and shorter time-to-sale.</p>
<p>— <a target="_blank" href="https://subgame.ir">SubGame Dev Team</a></p>
]]></content:encoded></item><item><title><![CDATA[Designing Trust & Fraud-Prevention for Game Marketplaces: Practical Patterns and Architecture]]></title><description><![CDATA[Introduction
Game marketplaces that let users buy/sell accounts, skins, currencies, or services are fundamentally marketplaces of trust. Players trade digital assets with real monetary value; a single high-profile fraud can damage reputation and liqu...]]></description><link>https://subgame.hashnode.dev/designing-trust-and-fraud-prevention-for-game-marketplaces-practical-patterns-and-architecture</link><guid isPermaLink="true">https://subgame.hashnode.dev/designing-trust-and-fraud-prevention-for-game-marketplaces-practical-patterns-and-architecture</guid><category><![CDATA[MarketplaceFlow ]]></category><category><![CDATA[marketplace]]></category><category><![CDATA[Security]]></category><category><![CDATA[full stack]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[FastAPI]]></category><category><![CDATA[Devops]]></category><category><![CDATA[websockets]]></category><category><![CDATA[gaming]]></category><category><![CDATA[product]]></category><dc:creator><![CDATA[SubGame]]></dc:creator><pubDate>Mon, 29 Sep 2025 16:58:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1759163989883/7497b93e-1c40-4331-a406-2be550622b3d.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>Game marketplaces that let users buy/sell accounts, skins, currencies, or services are fundamentally marketplaces of <em>trust</em>. Players trade digital assets with real monetary value; a single high-profile fraud can damage reputation and liquidity overnight. In this article, I’ll share practical building blocks and architectural patterns we used at SubGame to reduce fraud, speed dispute resolution, and keep user friction low — actionable advice you can apply to your own marketplace.</p>
<hr />
<h2 id="heading-why-trust-is-different-in-game-marketplaces">Why trust is different in game marketplaces</h2>
<p>Two differences change the game (pun intended):</p>
<ol>
<li><p><strong>Assets are account-bound &amp; recoverable.</strong> A sold account can often be reclaimed by the original owner if email/phone recovery is intact.</p>
</li>
<li><p><strong>High velocity, low-ticket &amp; collectible items.</strong> Many trades are small but frequent; some items are rare and high-value (sketchy sellers target both).</p>
</li>
</ol>
<p>So solutions must combine automated prevention, smart UX, and a fast human-in-the-loop process for edge cases.</p>
<hr />
<h2 id="heading-core-components-of-a-trust-architecture">Core components of a trust architecture</h2>
<ol>
<li><p><strong>Identity &amp; verification</strong></p>
<ul>
<li><p>Email + phone verification (SMS OTP).</p>
</li>
<li><p>Optional KYC for high-value sellers (name, ID, selfie).</p>
</li>
<li><p>Link external proofs: gaming platform profiles (Steam, Activision, Riot) or social accounts (Discord, Twitter) to raise confidence.</p>
</li>
</ul>
</li>
<li><p><strong>Escrow workflow</strong></p>
<ul>
<li><p>Buyer pays into escrow; funds are released only after verified delivery or after a timeout + seller confirmation.</p>
</li>
<li><p>Use a state machine for the order lifecycle: <code>PENDING -&gt; IN_ESCROW -&gt; DELIVERED -&gt; RELEASED | DISPUTED -&gt; RESOLVED</code>.</p>
</li>
<li><p>Log immutable events for audits.</p>
</li>
</ul>
</li>
<li><p><strong>Reputation &amp; trust score</strong></p>
<ul>
<li><p>Combine signals: completed sales, dispute rate, account age, verification level, and response time.</p>
</li>
<li><p>Present a clear seller score badge (e.g., Verified, Trusted, New) — transparency reduces buyer anxiety.</p>
</li>
</ul>
</li>
<li><p><strong>Automated fraud detection</strong></p>
<ul>
<li><p>Rule-based checks + ML signals (optional): rapid price drops, new account listing many high-value items, repeated chargebacks, inconsistent IP/geolocation vs declared country.</p>
</li>
<li><p>Real-time scoring to block suspicious listings or require manual review.</p>
</li>
</ul>
</li>
<li><p><strong>Dispute resolution &amp; human review</strong></p>
<ul>
<li><p>Lightweight UI for filing disputes with structured inputs (screenshots, timestamps).</p>
</li>
<li><p>Human reviewers for high-value or ambiguous cases; automation for low-value or obvious scams.</p>
</li>
</ul>
</li>
</ol>
<hr />
<h2 id="heading-practical-patterns-amp-snippets">Practical patterns &amp; snippets</h2>
<h3 id="heading-trust-score-example">Trust score (example)</h3>
<p>A simple weighted score you can iterate on:</p>
<p><code>trust_score = 0.4 normalized(completed_sales) + 0.25 (1 - normalized(dispute_rate)) + 0.2 verification_level + 0.1 account_age_score + 0.05 * response_time_score</code></p>
<p>Normalize values to 0–1. Tune weights based on observed fraud/fallout.</p>
<h3 id="heading-escrow-state-machine-pseudo">Escrow state machine (pseudo)</h3>
<p><code>Order { id, buyer_id, seller_id, amount, state }</code></p>
<p><code>states = { PENDING, IN_ESCROW, DELIVERED, RELEASED, DISPUTED, REFUNDED }</code></p>
<p>Transition rules must be guarded (e.g., only buyer confirmation triggers <code>DELIVERED</code>; dispute moves to <code>DISPUTED</code> and triggers review queue).</p>
<h3 id="heading-event-webhook-handler-simplified">Event webhook handler (simplified)</h3>
<p><code>FastAPI pseudo-handler</code></p>
<p><code>@</code><a target="_blank" href="http://app.post"><code>app.post</code></a><code>("/webhook/payment") async def payment_webhook(payload: PaymentPayload): order = get_order(payload.order_id) if payload.status == "paid": order.transition_to("IN_ESCROW") notify_user(order.seller_id, "Buyer paid — please deliver.")</code></p>
<hr />
<h2 id="heading-signals-worth-tracking-for-automated-detection">Signals worth tracking for automated detection</h2>
<ul>
<li><p>New seller listing &gt; X high-value items in Y hours</p>
</li>
<li><p>Price anomalies vs the marketplace median for the same item</p>
</li>
<li><p>Frequent account recovery attempts on the item’s original platform</p>
</li>
<li><p>IP/geolocation mismatches across seller actions</p>
</li>
<li><p>Multiple payment failures or chargebacks</p>
</li>
</ul>
<p>Use Redis or a streaming pipeline (Kafka) to build fast alerts and scoring.</p>
<hr />
<h2 id="heading-ux-considerations-reduce-friction-while-increasing-safety">UX considerations — reduce friction while increasing safety</h2>
<ul>
<li><p><strong>Progressive friction</strong>: only show verification/KYC when the risk score passes a threshold or the seller reaches a revenue tier.</p>
</li>
<li><p><strong>Clear timelines</strong>: explain escrow holds (“Funds released after 48 hours unless dispute filed”).</p>
</li>
<li><p><strong>Deliverability checklist</strong>: when sellers deliver an account, give a checklist to confirm handover (email changed, 2FA removed, recovery info updated).</p>
</li>
<li><p><strong>Default buyer protection</strong>: Have a visible “buyer protection” badge and link to the policy to increase conversions.</p>
</li>
</ul>
<hr />
<h2 id="heading-operational-playbook-for-disputes">Operational playbook for disputes</h2>
<ol>
<li><p>Triage automatically: low-value -&gt; auto-refund if evidence is obvious.</p>
</li>
<li><p>Medium/high-value -&gt; human reviewer within SLA (e.g., 24 hours).</p>
</li>
<li><p>Collector for evidence: logs, screenshots, transaction chain.</p>
</li>
<li><p>If the seller is fraudulent, ban + reclaim fees from seller's escrow or bond.</p>
</li>
</ol>
<p>Maintain a separate “trust fund” or insurance pool for refunds until your fraud rate decreases.</p>
<hr />
<h2 id="heading-instrumentation-amp-kpis">Instrumentation &amp; KPIs</h2>
<p>Track these closely:</p>
<ul>
<li><p>GMV (Gross Merchandise Value) &amp; GMV growth</p>
</li>
<li><p>Dispute rate (%) per 1,000 transactions</p>
</li>
<li><p>False positives (blocked legitimate listings)</p>
</li>
<li><p>Time-to-resolution for disputes</p>
</li>
<li><p>Seller lifetime value (LTV) by verification tier</p>
</li>
</ul>
<p>Use dashboards (Grafana) and alerts for KPIs crossing thresholds.</p>
<hr />
<h2 id="heading-scaling-considerations">Scaling considerations</h2>
<ul>
<li><p><strong>Stateful services</strong> (escrow, disputes) must be ACID-safe: Postgres + strong transactional boundaries.</p>
</li>
<li><p><strong>Real-time systems</strong> (such as chat/notifications) scale with Redis pub/sub or managed WebSocket layers.</p>
</li>
<li><p><strong>Batch &amp; stream processing</strong> for fraud signals: stream events to Kafka and run real-time scoring via Flink/Spark or a lightweight Python worker.</p>
</li>
</ul>
<hr />
<h2 id="heading-legal-amp-privacy-notes">Legal &amp; privacy notes</h2>
<ul>
<li><p>Know local laws: trading digital goods might require taxation, VAT handling, or be regulated.</p>
</li>
<li><p>For KYC, handle PII securely: store encrypted, have retention policies, and publish privacy terms.</p>
</li>
</ul>
<hr />
<h2 id="heading-conclusion">Conclusion</h2>
<p>Trust is the currency of any marketplace — for game marketplaces, investing early in identity verification, escrow, reputation systems, and automated fraud detection pays off by improving liquidity and user retention. Start with simple, explainable rules, instrument everything, and iterate: your scoring models and rules will get better with data.</p>
<p>If you'd like, I can provide a concrete implementation plan (including DB schemas, API specs, and a review checklist) that you can integrate with your Next.js + FastAPI stack.</p>
<p>— <a target="_blank" href="https://subgame.ir/">SubGame Dev Team</a></p>
]]></content:encoded></item><item><title><![CDATA[Building a Secure and Scalable Game Marketplace with Next.js and FastAPI]]></title><description><![CDATA[Introduction:
The gaming industry has grown exponentially in recent years, not only as a source of entertainment but also as a thriving economy. Players spend hours leveling up accounts, unlocking rare items, and collecting in-game currencies. This c...]]></description><link>https://subgame.hashnode.dev/building-a-secure-and-scalable-game-marketplace-with-nextjs-and-fastapi</link><guid isPermaLink="true">https://subgame.hashnode.dev/building-a-secure-and-scalable-game-marketplace-with-nextjs-and-fastapi</guid><category><![CDATA[Dev Community]]></category><category><![CDATA[Tailwind CSS]]></category><category><![CDATA[websockets]]></category><category><![CDATA[PostgreSQL]]></category><category><![CDATA[Game Development]]></category><category><![CDATA[gaming marketplace]]></category><category><![CDATA[FastAPI]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[Full Stack Development]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[SubGame]]></dc:creator><pubDate>Tue, 23 Sep 2025 11:49:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1758627544412/1792b927-31a2-4792-b44b-f8e120b1546c.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introduction"><strong>Introduction:</strong></h3>
<p>The gaming industry has grown exponentially in recent years, not only as a source of entertainment but also as a thriving economy. Players spend hours leveling up accounts, unlocking rare items, and collecting in-game currencies. This creates a huge market for <strong>buying and selling game accounts and items</strong>.</p>
<p>To address this need, I started <strong>SubGame</strong>, a platform designed to provide <strong>gamers with a secure, fast, and transparent marketplace</strong>. In this article, I’ll walk through the tech stack, architecture, and key lessons learned while building SubGame.</p>
<hr />
<h3 id="heading-tech-stack-overview"><strong>Tech Stack Overview:</strong></h3>
<ul>
<li><p><strong>Frontend:</strong> Next.js + React + TailwindCSS for responsive, SEO-friendly, and high-performance UI</p>
</li>
<li><p><strong>Backend:</strong> FastAPI for fast, async APIs with Python</p>
</li>
<li><p><strong>Database:</strong> PostgreSQL for relational data</p>
</li>
<li><p><strong>Caching &amp; Queues:</strong> Redis for high-speed caching and message queues</p>
</li>
<li><p><strong>Authentication &amp; Security:</strong> JWT-based auth and secure token storage</p>
</li>
<li><p><strong>Realtime Features:</strong> WebSockets for chat and notifications</p>
</li>
<li><p><strong>Infrastructure:</strong> Docker, Docker Compose, VPS, CDN (ArvanCloud)</p>
</li>
<li><p><strong>Version Control &amp; CI/CD:</strong> GitHub + GitHub Actions</p>
</li>
</ul>
<hr />
<h3 id="heading-key-features-of-subgame"><strong>Key Features of SubGame:</strong></h3>
<ol>
<li><p><strong>Secure Transactions:</strong> Users’ payments are held in escrow until the item is delivered.</p>
</li>
<li><p><strong>Wide Game Support:</strong> From <strong>PUBG, Call of Duty, Clash of Clans, CS2, Dota 2, World of Warcraft</strong> to many more.</p>
</li>
<li><p><strong>Realtime Notifications &amp; Chat:</strong> Players can communicate instantly and track orders.</p>
</li>
<li><p><strong>User-Friendly Dashboard:</strong> Sellers can manage listings, and buyers can filter and sort for the best deals.</p>
</li>
</ol>
<hr />
<h3 id="heading-challenges-and-lessons-learned"><strong>Challenges and Lessons Learned:</strong></h3>
<ul>
<li><p><strong>JWT Management:</strong> Ensuring token security and session management was crucial for protecting users.</p>
</li>
<li><p><strong>Realtime Scaling:</strong> Handling chat and notification systems for thousands of concurrent users required careful planning with WebSockets.</p>
</li>
<li><p><strong>SEO and Performance:</strong> Using Next.js for SSR and SSG helped improve search visibility and site speed.</p>
</li>
</ul>
<hr />
<h3 id="heading-conclusion"><strong>Conclusion:</strong></h3>
<p>Building SubGame has been an exciting journey combining <strong>gaming passion with web development expertise</strong>. The platform empowers gamers with a <strong>safe and reliable way to trade accounts and items</strong>, while also serving as a case study for modern full-stack development using <strong>Next.js and FastAPI</strong>.</p>
<p>Check out the platform here: <a target="_blank" href="https://subgame.ir">SubGame - Game Marketplace</a></p>
]]></content:encoded></item></channel></rss>