◉GEMINI LABJP
●ARGON — gemini-4-argon is generally available as of 10/13, aimed at complex coding, agents, math and science●DEEP RES — deep-research-pro-preview-12-2025 shuts down 10/23, 5 days left. Move to deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 is GA (10/06). gemini-3.1-flash-image is deprecated with no shutdown date yet●MCP — One write-up cut an 85,000-token tool result to 310 tokens by wrapping it in an ADK FunctionTool●FLASH — gemini-3.7-flash and 3.5-flash now route automatically to newer Flash models (10/08)●NEW — Stop Re-Reading Every Crash Report: Gre…●ARGON — gemini-4-argon is generally available as of 10/13, aimed at complex coding, agents, math and science●DEEP RES — deep-research-pro-preview-12-2025 shuts down 10/23, 5 days left. Move to deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 is GA (10/06). gemini-3.1-flash-image is deprecated with no shutdown date yet●MCP — One write-up cut an 85,000-token tool result to 310 tokens by wrapping it in an ADK FunctionTool●FLASH — gemini-3.7-flash and 3.5-flash now route automatically to newer Flash models (10/08)●NEW — Stop Re-Reading Every Crash Report: Gre…
Articles/API / SDK
◈ API / SDK/2026-03-23Advanced

Running a Gemini + LINE Bot in Production — Reply Token Expiry, Duplicate Replies, and Cold-Start Latency

The first walls you hit putting Gemini behind a LINE Bot are the 30-second reply-token expiry, duplicate replies from webhook redelivery, and Cloud Run cold starts. This guide solves them with loading animations, push-message fallback, idempotency, and Firestore-backed history — with working code and measured numbers.

gemini119gemini-api286line-botpython108cloud-run6production140

✦ Premium Article

As an indie developer at Dolice, I put Gemini behind a LINE Bot and everything worked perfectly through ngrok on my machine. The morning after I shipped it to Cloud Run, the reports started: "it replies twice" and "sometimes it just goes silent."

Neither was a bug in my code. The LINE Messaging API, a generative model that takes a few seconds, and serverless cold starts simply weren't aligned on the same clock.

This is the record of how I re-aligned them — with working code and the numbers I measured. It still works as a tutorial you can follow from first setup, but most of the space goes to the traps that only show up in production.

If the Gemini API itself is new to you, the Gemini API Quickstart is a gentler starting point.


Get a Minimal Version Running First

Before the traps, let's stand up the smallest version that works. Without this foundation, the later discussion has nothing to stand on.

What You'll Need

  • Python 3.11+
  • A Google AI Studio API key (free at Google AI Studio)
  • A LINE Developers account (free at LINE Developers)
  • ngrok (HTTPS tunnel for local testing) or Google Cloud Run (production)

Creating a LINE Channel

  1. Sign in to the LINE Developers Console
  2. Create a Provider (e.g., My AI Bot)
  3. Create a Messaging API channel
  4. From the channel settings, note two values:
    • Channel secret (Basic settings tab)
    • Channel access token (Messaging API tab → "Issue")
  5. You'll set the Webhook URL later

Installing Packages

mkdir gemini-line-bot && cd gemini-line-bot
python -m venv venv
source venv/bin/activate
pip install google-genai flask line-bot-sdk gunicorn google-cloud-firestore

Keep secrets in a .env file.

# .env
GEMINI_API_KEY=your_gemini_api_key_here
LINE_CHANNEL_SECRET=your_channel_secret_here
LINE_CHANNEL_ACCESS_TOKEN=your_channel_access_token_here

Smoke Test

Confirm Gemini works on its own first.

# test_gemini.py
from google import genai
 
client = genai.Client(api_key="YOUR_GEMINI_API_KEY")
 
response = client.models.generate_content(
    model="gemini-3-flash",
    contents="Hello! Please introduce yourself briefly.",
)
print(response.text)

For a chatbot backend I recommend gemini-3-flash — the balance of speed and price is hard to beat. I switch to gemini-3-pro only for the moments that genuinely need deeper reasoning, which keeps both cost and latency reasonable.


Why a Naive reply_message Breaks in Production

Most samples call Gemini the moment the webhook arrives and return the text via reply_message. Locally, this is fine.

In production, two properties of the LINE reply token start to bite.

First, the reply token expires roughly 30 seconds after it's issued. Second, each reply token can only be used once.

Gemini Flash is fast, but a longer prompt or a busy moment can take several seconds. Stack a Cloud Run cold start on top and you occasionally creep toward that 30-second edge. Reply to an expired token and LINE returns 400 Invalid reply token — the user just gets silence.

Redelivery makes it worse. If your webhook doesn't return 200 quickly enough, LINE resends the same event. Call Gemini and reply on every resend, and the user receives the same answer two or three times. That was the "it replies twice" I hit on day one.

The rest of this guide takes both problems — token expiry and redelivery — head on.


✦

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
✦A concrete way to work around the ~30-second, single-use reply token using a loading animation plus push-message fallback
✦How to stop duplicate replies caused by webhook redelivery by making each event idempotent with its event ID
✦Measured ~4s cold-start penalty on Cloud Run with min-instances 0, and why conversation history belongs in Firestore
Secure payment via Stripe · Cancel anytime
✦

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Gemini Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

Related Articles

◈ API / SDK2026-09-04
Screen Loop Seam Clicks With Numbers Before You Hand the Audio to Gemini
An ambient loop that clicks only at the wrap point. Here is the numeric prescreen I run before sending anything to audio understanding, why an absolute threshold fails, and how AAC encoding quietly rebuilt the seam I had just repaired.
◈ API / SDK2026-07-15
Sample what you already accepted — an audit budget that catches silent quality drift
A confidence gate only ever looks at output the model hesitated on. Silent drift sinks into the batch that sailed through. Working from a fixed 30-minutes-a-day review budget, this walks through deriving detection time from the binomial, reallocating the same budget across risk strata, and catching slow decay with a cumulative monitor.
◈ API / SDK2026-07-04
When Gemini API Leaks Japanese Into Your English Output Once in a While — Field Notes on Measuring the Contamination Rate and Tightening It in Stages
You told Gemini to answer in English, and 3 out of 100 runs slip a Japanese sentence into the tail. Here is why you cannot stop that 'once in a while', and a production pattern that measures the contamination rate as an SLO and tightens it with graded recovery, with working code.