DEV Community

Cover image for Benchmarking Cyber Deception: Why Legacy Honeypots Fail Under High Concurrency (And How EchidraOSS Fixes It)
Qyleron
Qyleron

Posted on Edited on Originally published at qyleron.com

Benchmarking Cyber Deception: Why Legacy Honeypots Fail Under High Concurrency (And How EchidraOSS Fixes It)

A concurrency comparison of Cowrie, Thinkst Canary, and generic Twisted listeners against EchidraOSS's async FastAPI core. The difference shows up exactly when it matters most: under a connection flood.

Most honeypot evaluations compare feature checklists: protocol coverage, decoy realism, alerting integrations. Those details matter, but they skip the variable that actually decides whether a deception layer survives contact with the internet. That variable is simple: what happens to the listener process when a hundred connections arrive in the same second.

This isn't a hypothetical. Mass-scanning botnets, credential-stuffing swarms, and internet-wide research crawlers such as Shodan and Censys don't trickle in. They arrive in bursts. A deception system that can't absorb a burst doesn't fail gracefully. It drops connections, skips logging, or pins a CPU core, and that's precisely the moment you lose the session data the honeypot was deployed to capture.

We built EchidraOSS around that failure mode instead of treating it as an afterthought. This post breaks down why the dominant architectures in the honeypot space, including Cowrie's Twisted reactor and the raw Twisted or socket listeners teams often build themselves, hit a concurrency ceiling, and how Thinkst Canary's managed appliance model sidesteps it. Then it covers what EchidraOSS does differently at the architecture level.
 

1. Asynchronous concurrency: the event loop is the whole story

Cowrie is built on Twisted's reactor pattern, an event-driven model that predates asyncio by over a decade. The reactor is also a single-threaded event loop, so the model itself isn't the limit. The limit is whatever runs on the loop: any blocking or CPU-heavy step in a callback holds up every other connection, so a burst of new SSH negotiations competes for the same loop turn as everything already in flight. Generic, self-built listeners usually have a lower ceiling: many use a thread per connection or blocking socket reads, and they lack Cowrie's years of incremental tuning.

Thinkst Canary sidesteps the software problem by shipping a managed appliance. It solves concurrency by dedicating hardware or a locked-down VM to the problem, not by fixing the underlying model. That approach works, and it's also why Canary is priced and deployed as infrastructure rather than as software you drop into an existing box.

EchidraOSS's listeners and API run on Python 3.11+ with FastAPI's async event loop. Every connection handler is a coroutine, not a thread and not a blocking socket read. When a scanning bot opens fifty SSH connections in the same second, those connections don't each claim a thread. They're all suspended on I/O at once, and the loop services whichever one has data ready, in the order the operating system delivers it. The slow work, classifying and storing each finished session, is handed to a small, bounded pool of background workers, so it never runs on the loop and a flood can't grow the backlog without limit. There's no thread-per-connection overhead and no context-switch cost that scales linearly with load.

 

The practical effect: the listener doesn't spend a thread per connection, so connection count isn't what drives its CPU cost.

 

What that looks like in practice: in our own test, a 10-second burst of 1,000 HTTP requests at 100 per second kept the honeypot process working at 100 to 130% CPU for about 79 seconds while it classified and stored the sessions, then it dropped straight back to idle. Memory stepped up once on first traffic and stayed flat afterward. Every session still costs real work, and that work outlasts the flood itself. The architecture keeps the cost tied to the requests, not to the number of open connections.

 

Line chart showing EchidraOSS honeypot CPU rising to about 130% during a 10-second request flood, staying elevated for about 79 seconds while the backlog is processed, then dropping straight back to idle
Fig. 1: EchidraOSS CPU during and after a request flood, measured with the public benchmark.

 

2. Low memory footprint: deployable on a VPS for about $6 a month

Concurrency headroom only helps if it doesn't cost you a fleet of memory. This is where Cowrie's process model and self-built Twisted listeners tend to sprawl. Every open session carries its own buffered state and protocol objects, and Cowrie specifically adds a simulated filesystem context per connection. That overhead adds up fast once you're running SSH, HTTP, FTP, and Telnet decoys side by side.

EchidraOSS keeps its footprint down through modular service design. The honeypot listeners, with their classification workers, and the dashboard API run as separate processes that share a single PostgreSQL instance instead of each maintaining redundant in-memory state. Session objects are short-lived: they exist as coroutine-local state for the duration of the connection, get classified, get written to Postgres, and are released. In our tests, memory grew only slightly after its initial step up on first traffic.

That design is exactly why the reference deployment path (see the Setup and Onboarding guide) runs comfortably as a single Docker Compose stack, honeypot listeners, dashboard API, and PostgreSQL together, on a 1 vCPU, 1GB RAM instance that costs about $6 a month at providers such as DigitalOcean, Vultr, or Hetzner. You're sizing for a modest, observed footprint, not a worst-case ceiling.

 

Bar chart showing EchidraOSS resident memory at idle (50MB) and after three request floods (156MB each), stepping up once and then staying flat
Fig. 2: EchidraOSS memory before and after a request flood, measured with the public benchmark.

 

3. Real-time log classification: no post-processing pipeline required

This is the gap that matters most once you're running one of these tools in production. Cowrie, generic Twisted listeners, and most self-built setups write unstructured text logs, whether that's JSON lines or flat text, with no semantic layer on top. Turning "attacker ran cat /etc/passwd, then downloaded a binary with wget" into "this was a credential-harvesting attempt followed by second-stage payload retrieval, MITRE T1552 and T1105" is left entirely to you: a Logstash pipeline, a Splunk query, or a homegrown script that somebody has to maintain and retune every time attacker tooling shifts. Thinkst Canary does better here with its own hosted console, but the classification logic is closed. You get an alert, not an inspectable rule trail.

EchidraOSS classifies sessions natively, at capture time, using a deterministic rule engine. It's not an LLM call and not a black box. Every closed session runs through classification rules that assign an actor label (for example, brute_force_bot), an intent such as reconnaissance, credential theft, or persistence, a risk score from 0 to 100, and one or more MITRE ATT&CK technique IDs, all before the session reaches a dashboard query. Because the rules are deterministic pattern matches over observed command and request behavior rather than a model inference call, classification runs in-process at session close. There's no network round trip, no queueing on an inference server, and no variance from a probabilistic model changing its answer between runs.

The downstream result is what the Console Guide calls Intelligence. Instead of a flat firehose of logs, recurring actor-and-technique pairs get grouped into issues with evidence, a recommended fix, and an impact summary, pulled from the same built-in playbook that generated the classification. The reasoning behind every flag stays inspectable, not a mystery.

 

EchidraOSS Issue Intelligence dashboard showing a table of grouped attacker issues by MITRE ATT&CK technique, with the Issue Detail panel open showing Evidence, Recommended Fix, and Impact
Fig. 3: The Intelligence view grouping recurring sessions into issues by actor and MITRE ATT&CK technique.

 

Head-to-head: architecture

The table below reflects the structural properties of each project's public architecture, plus EchidraOSS's own load testing. Treat the figures as directional. The point isn't the third decimal place. It's the order of magnitude, and much of that difference traces back to the concurrency model rather than to tuning.

Methodology note: EchidraOSS figures come from Qyleron's own load testing, which is public and reproducible: see the benchmarks folder. Cowrie and Thinkst Canary figures are drawn from each project's public documentation and community-reported deployment experience, not from independent lab testing we ran ourselves. Treat them as representative, not as a controlled benchmark.

 

METRIC COWRIE THINKST CANARY GENERIC TWISTED LISTENER EchidraOSS
Concurrency model Twisted reactor, single-threaded event loop, prone to blocking Managed appliance, concurrency solved by hardware and not exposed Twisted or raw sockets, usually thread per connection Python 3.11, FastAPI async event loop
Memory footprint Roughly 250 to 400MB idle, climbs with concurrent simulated-filesystem sessions Not applicable. Fixed appliance or VM allocation, not user-tunable 200MB or more idle, scales roughly linearly with open threads About 50MB idle, about 150MB after a request flood (our tests)
Parsing and classification speed None native. Offline log parsing required Proprietary, cloud-side, latency not disclosed None native. Raw logs only Deterministic, resolved in-process at session close
MITRE ATT&CK mapping Not built in. Requires external tooling Alerting only, no exposed technique-level mapping Not built in Native, per session, with an inspectable evidence trail
Deployment overhead Manual Python, Twisted, and log pipeline setup Vendor-managed hardware or appliance provisioning Fully manual, no packaged deployment path A single docker compose up, or systemd on a bare VM
Minimum viable hardware Small VM, though the log pipeline usually needs a second host Dedicated appliance or cloud instance, vendor-sized Small VM, degrades under concurrent load 1 vCPU, 1GB: about a $6 a month cloud VPS

 

Why this is an architecture problem, not a tuning problem

You can add more RAM to Cowrie or hand-tune a Twisted reactor's thread pool. Neither changes the underlying model. You'd be compensating for blocking I/O and unstructured logging with infrastructure spend instead of fixing what's actually blocking. EchidraOSS's advantage isn't a set of tuning flags. The async event loop and the deterministic classifier are load-bearing parts of the design from the first connection handler onward. The same code path runs at idle and under load. The async model is the path.

That's also why the comparison holds up on cheap hardware. A honeypot that only performs well on generously provisioned infrastructure isn't solving the deployment problem most teams actually have: running deception at the edges of their network, cheaply, in enough places that coverage is real instead of symbolic.

 

📦 Run it yourself

EchidraOSS is open-source under AGPLv3. Clone it, point it at a VPS that costs about $6 a month, and watch the classification engine work in real time.

👉 Clone the GitHub Repository

👉 Reproduce the benchmarks

Top comments (0)