diff --git a/bench/consume.go b/bench/consume.go
new file mode 100644
index 0000000000000000000000000000000000000000..195c232fcb1bbe934b3a561f5b5ab3a4bfd84128
--- /dev/null
+++ b/bench/consume.go
@@ -0,0 +1,32 @@
+package main
+
+import (
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"time"
+)
+
+func Consume(add string, interv int, run *bool) error {
+	u, e := url.Parse(add)
+	if e != nil {
+		return e
+	}
+	u.Path = "/out/"
+
+	t := time.NewTicker(time.Millisecond * time.Duration(interv))
+
+	for *run {
+		_ = <-t.C
+		resp, e := http.Get(u.String())
+		if e != nil {
+			return e
+		}
+		_, e = ioutil.ReadAll(resp.Body)
+		if e != nil {
+			return e
+		}
+	}
+
+	return nil
+}
diff --git a/bench/main.go b/bench/main.go
new file mode 100644
index 0000000000000000000000000000000000000000..cc37737ddd67ac504aaf96f9e451c4cb9a7f7cc2
--- /dev/null
+++ b/bench/main.go
@@ -0,0 +1,85 @@
+package main
+
+import (
+	"flag"
+	"fmt"
+	"math/rand"
+	"strings"
+	"time"
+)
+
+type stringSlice []string
+
+func (s *stringSlice) String() string {
+	return strings.Join(*s, " ")
+}
+
+func (s *stringSlice) Set(value string) error {
+	*s = append(*s, value)
+	return nil
+}
+
+func (s *stringSlice) RandElement() string {
+	l := len(*s)
+	if l == 0 {
+		return ""
+	}
+	n := rand.Intn(l)
+	return (*s)[n]
+}
+
+var (
+	loc            = flag.String("locations", "http://localhost:8080", "location of server")
+	prod           = flag.Int("producers", 100, "number of producers")
+	cons           = flag.Int("consumers", 1, "number of consumers")
+	prodInt        = flag.Int("prod-interval", 1000, "interval of clicks in ms")
+	consInt        = flag.Int("cons-interval", 1000, "interval of loads in ms")
+	teams, choices stringSlice
+)
+
+func init() {
+	flag.Var(&teams, "team", "add team")
+	flag.Var(&choices, "choice", "add choice")
+}
+
+func main() {
+	flag.Parse()
+
+	run := true
+	proderr := make(chan error)
+	conserr := make(chan error)
+
+	prodSleep := time.Duration(float64(*prodInt) / float64(*prod))
+	for i := 0; i < *prod; i++ {
+		go func() {
+			proderr <- Produce(*loc, *prodInt, &run, teams, choices)
+		}()
+		time.Sleep(prodSleep)
+	}
+
+	consSleep := time.Duration(float64(*consInt) / float64(*cons))
+	for i := 0; i < *cons; i++ {
+		go func() {
+			conserr <- Consume(*loc, *consInt, &run)
+		}()
+		time.Sleep(consSleep)
+	}
+
+	fmt.Println("started benchmark")
+	fmt.Println("voters:", *prod)
+	fmt.Println("voting interval:", *prodInt)
+	fmt.Println("consumers:", *cons)
+	fmt.Println("consumer interval:", *consInt)
+	fmt.Println("teams:", teams.String())
+	fmt.Println("choices:", choices.String())
+
+	for {
+		select {
+		case err := <-conserr:
+			fmt.Println("consumer error:", err)
+		case err := <-proderr:
+			fmt.Println("producer error:", err)
+		}
+	}
+
+}
diff --git a/bench/produce.go b/bench/produce.go
new file mode 100644
index 0000000000000000000000000000000000000000..be5f982d7afdf6aa548a6b7a1f4f71f0cf08a91a
--- /dev/null
+++ b/bench/produce.go
@@ -0,0 +1,53 @@
+package main
+
+import (
+	"github.com/gorilla/websocket"
+	"net/url"
+	"time"
+)
+
+func Produce(add string, interv int, run *bool, teams, choices stringSlice) error {
+	u, e := url.Parse(add)
+	if e != nil {
+		return e
+	}
+	u.Scheme = "ws"
+	u.Path = "/in/websocket"
+
+	c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
+	if err != nil {
+		return err
+	}
+
+	d := make(chan error)
+
+	go func() {
+		for {
+			_, _, err := c.ReadMessage()
+			if err != nil {
+				d <- err
+				return
+			}
+		}
+	}()
+
+	err = c.WriteMessage(websocket.TextMessage, []byte(teams.RandElement()))
+	if err != nil {
+		return err
+	}
+
+	ticker := time.NewTicker(time.Millisecond * time.Duration(interv))
+
+	go func() {
+		for *run {
+			_ = <-ticker.C
+			e := c.WriteMessage(websocket.TextMessage, []byte(choices.RandElement()))
+			if e != nil {
+				d <- e
+				return
+			}
+		}
+	}()
+
+	return <-d
+}
diff --git a/docker-compose.yml b/docker-compose.yml
index dd8527a29e75abeda5f97c9c9f1c80b015c17d22..345188956c5469644d82333e0cacbcf466124c5d 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -21,6 +21,8 @@ services:
       - POSTGRES_PASSWORD=matrix
       - POSTGRES_USER=matrix
       - POSTGRES_DB=matrix
+    volumes:
+      - postgres:/var/lib/postgresql/data
 
 volumes:
   postgres:
\ No newline at end of file
diff --git a/go.mod b/go.mod
index b5087038551f20651e329e468a69241918d46cf0..fb3658fc9f1688573622354d5f96589030d10664 100644
--- a/go.mod
+++ b/go.mod
@@ -6,6 +6,7 @@ go 1.15
 
 require (
 	github.com/go-pg/pg/v10 v10.7.5
+	github.com/gorilla/websocket v1.4.2
 	github.com/igm/sockjs-go/v3 v3.0.0
 	github.com/prometheus/client_golang v1.9.0
 	gitlab.com/MikeTTh/env v0.0.0-20210102155928-2e9be3823cc7