diff --git a/include/osmo-bts/gsm_data.h b/include/osmo-bts/gsm_data.h
index 42c1440..a5ac9e2 100644
--- a/include/osmo-bts/gsm_data.h
+++ b/include/osmo-bts/gsm_data.h
@@ -49,6 +49,7 @@ struct gsm_bts_role_bts {
 	uint8_t ny1;
 	uint8_t max_ta;
 	struct llist_head agch_queue;
+	int agch_queue_count;
 	struct paging_state *paging_state;
 	char *bsc_oml_host;
 	unsigned int rtp_jitter_buf_ms;
diff --git a/src/common/bts.c b/src/common/bts.c
index c94da22..6ae60c7 100644
--- a/src/common/bts.c
+++ b/src/common/bts.c
@@ -216,8 +216,11 @@ int bts_agch_enqueue(struct gsm_bts *bts, struct msgb *msg)
 {
 	struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
 
-	/* FIXME: implement max queue length */
+	if (btsb->agch_queue_count >= 30)
+		return -ENOMEM;
+
 	msgb_enqueue(&btsb->agch_queue, msg);
+	btsb->agch_queue_count++;
 
 	return 0;
 }
@@ -225,8 +228,11 @@ int bts_agch_enqueue(struct gsm_bts *bts, struct msgb *msg)
 struct msgb *bts_agch_dequeue(struct gsm_bts *bts)
 {
 	struct gsm_bts_role_bts *btsb = bts_role_bts(bts);
+	struct msgb *msg = msgb_dequeue(&btsb->agch_queue);
 
-	return msgb_dequeue(&btsb->agch_queue);
+	if (msg)
+		btsb->agch_queue_count--;
+	return msg;
 }
 
 int bts_supports_cipher(struct gsm_bts_role_bts *bts, int rsl_cipher)
