How to Design a Ribosome Binding Site for E. coli
13 min read · Updated August 11, 2026
You reuse the expression cassette that worked last time — same promoter, same plasmid, same ribosome binding site — swap in a different coding sequence, and get a fraction of the protein. Nothing you changed was supposed to affect translation.
This guide covers why an RBS does not have a fixed strength, what a translation-initiation model actually computes, and how to choose a 5' UTR for a specific coding sequence. Every number below is real output from the tool described at the end, produced while writing this and reproducible from the sequences given. If your problem is that a codon-optimised gene expresses badly, that is a different failure mode, covered separately.
An RBS part does not have a strength of its own
The parts-registry model encourages the opposite belief. BBa_B0034 is listed in the iGEM Registry as "RBS (Elowitz 1999) -- defines RBS efficiency" — it is the part against which the others were scaled, a 12 bp basic part, 33.3% GC, created in January 2003. The Registry records it as used in 13,384 other parts. A number attached that firmly to a sequence looks like a property of that sequence.
It is not. Here are two runs that differ in exactly one thing. Both use the same 38 nt 5' UTR — a 20 nt unstructured poly-A leader, then B0034's AAAGAGGAGAAA, then a six-nucleotide spacer — and both are scored at the annotated start codon, which sits at position 39 in each. The only difference is which coding sequence follows.
In front of a GFP coding sequence, the predicted initiation rate is 29,915. In front of an mCherry coding sequence, 20,052. That is a 1.5-fold difference produced by the CDS alone, and the free-energy breakdown says exactly where it comes from: the 16S rRNA:mRNA hybridisation term is identical at −9.08 kcal/mol in both — the Shine-Dalgarno sequence has not changed — while the mRNA-unfolding term is −1.9 kcal/mol for GFP and −2.9 for mCherry. The mCherry 5' end folds slightly harder, and the ribosome pays the difference.
Change what sits upstream and the gap widens sharply. Rerun the same two constructs behind a 43 nt leader instead of the 20 nt poly-A one and the same B0034 gives 7,376 for GFP and 817 for mCherry — nine-fold apart, again with an identical −9.18 kcal/mol hybridisation term and an unfolding term that moves from −5.5 to −11.0. The interaction is between the whole 5' region and the start of the CDS, not between the SD sequence and the ribosome alone.
None of this is a quirk of one model. The original method paper says it outright: Salis, Mirsky and Voigt reported that their design method "correctly predicted that reusing identical ribosome binding site sequences in different genetic contexts can result in different protein expression levels" (Nat Biotechnol 2009;27:946-50, doi:10.1038/nbt.1568). A relative-strength table for RBS parts is a statement about the constructs those parts were measured in.
What the model computes, and what the number means
A translation-initiation-rate model is a thermodynamic calculation, not a machine-learning score. It folds the mRNA around each candidate start codon and adds up the free-energy cost of assembling the 30S initiation complex there. Five terms carry all the meaning:
- ΔG(rRNA:mRNA) — how well the Shine-Dalgarno region hybridises to the 3' end of the 16S rRNA. This is the term the SD sequence controls, and it is the only one that changes when you change the SD core alone.
- ΔG(mRNA) — the cost of unfolding whatever structure the mRNA has around the initiation region. This is where the coding sequence's own 5' end gets a vote.
- ΔG(spacing) — a penalty for the distance between the SD hybridisation site and the start codon being away from optimal.
- ΔG(standby) — the standby site: a stretch immediately 5' of the SD that has to be unpaired for the ribosome to load.
- ΔG(start codon) — initiator-tRNA binding, which is a fixed per-codon constant rather than something you can tune.
The exponential is the part people misread
Those terms combine into a single ΔG(total), and the reported rate is an exponential of it. In OSTIR — the open-source engine described at the end of this guide — the constants are in the source: expression = exp(7.279194329 − ΔG(total)/2.4998), where the 2.4998 kcal/mol is 1/β with β = 0.40002512, both fitted against the Salis 2009 measurements.
You can check that arithmetic against any output. An mCherry construct reporting ΔG(total) = −6.57 kcal/mol comes back at 20,052; the formula gives 20,078, and the gap is the two-decimal rounding on the reported ΔG. This matters practically, not as trivia: because the relationship is exponential, one kcal/mol is a factor of 1.49, and a ten-fold change in rate costs 5.76 kcal/mol. A design change that buys you half a kilocalorie is worth about 22%.
The number itself has no units and is not a protein concentration. Ratios between two predictions from the same model are the meaningful output; the absolute value is not. Treat it the way you would treat an arbitrary fluorescence unit — fine for ranking, meaningless in isolation.
Shine-Dalgarno core and spacing: what actually moves the number
The anti-Shine-Dalgarno sequence is the nine bases at the 3' end of the 16S rRNA. OSTIR's default is E. coli's ACCTCCTTA, and it is a parameter — you can supply another organism's, which is the only host-specific knob the model has.
Spacing is the second lever, and it is more forgiving than most protocols imply. The model's optimum is an aligned spacing of 5 nt, with an asymmetric penalty either side. Here is one SD core, AGGAGG, swept across spacer lengths in front of the same GFP CDS — the tool builds the spacer, the model reports its own aligned distance:
- aligned distance 4 nt — ΔG(spacing) 0.00 — rate 212,770
- aligned distance 5 nt — ΔG(spacing) 0.00 — rate 213,098
- aligned distance 6 nt — ΔG(spacing) 0.34 — rate 186,010
- aligned distance 7 nt — ΔG(spacing) 0.81 — rate 154,233
- aligned distance 8 nt — ΔG(spacing) 1.40 — rate 121,481
Reading that sweep
Being one nucleotide off optimum costs about 13%, two costs about 28%, three about 43%. That is real but it is not the difference between a band and no band. If you are troubleshooting a construct that expresses a hundred-fold below what you wanted, spacing is not where the hundred-fold is hiding — structure or the SD core is.
The SD core is the bigger lever, and it is bounded. Going from B0034's AAAGAGGAGAAA to a full AGGAGG core moves the hybridisation term from −9.08 to −14.08 kcal/mol, and extending to AGGAGGU reaches −15.38. Five kcal/mol is roughly a 7-fold change in rate — which is most of what RBS engineering has to offer before you start changing the coding sequence itself.
Why candidates have to be scored against your own CDS
This is the practical consequence of the first section, and it shows up cleanly when you rank the same candidate set against two different genes. Same generator, same poly-A leader, same B0034 baseline in both cases:
For the GFP CDS, the top candidate is AGGAGG with a 6 nt spacer: 213,098, a 7.1-fold improvement on the B0034 baseline of 29,915. For the mCherry CDS, the top candidate is AGGAGGU with a 5 nt spacer: 260,282, a 13.0-fold improvement on its baseline of 20,052.
The interesting part is the loser. AGGAGGU has the stronger hybridisation term of the two cores — −15.38 against −14.08 kcal/mol — so on a parts table it would win every time. In front of GFP it ranks fifth, because with that extra U the unfolding term moves from −2.8 to −5.0 kcal/mol: the region around the start folds harder, and that costs more than the stronger SD gained. In front of mCherry the same core costs nothing extra — −3.6 kcal/mol either way — and wins.
So the ranking of a fixed candidate list is not transferable between genes. That is the whole argument for scoring in context rather than picking from a table, and it is why a design tool needs your coding sequence and not just a target strength.
Check the start codons you did not design
A prediction run scores every start codon in the sequence, not just the one you meant. AUG, GUG and UUG are all scored (CTG is not, despite having an energy in the table), and the result is often more informative than the number you were looking for.
In the mCherry construct above, the annotated start at position 39 scores 20,052 — and an internal AUG at position 66 scores 6,821. That internal codon is mCherry's own codon 10, it is in frame, and it has the strongest hybridisation term in the whole construct (−12.38 kcal/mol, against −9.08 for the real start) because the sequence upstream of it happens to be purine-rich. At 34% of the annotated start's rate — and 23% of the total across every start codon in the construct — the model is saying a substantial minority of initiation events could begin nine codons in, giving a protein that is nine residues short at the N terminus.
Run the same check on the GFP construct and the story is different: the best competitor scores 354, about 1% of the annotated start. Same vector context, same RBS — one gene has an internal initiation problem and the other does not, and you only find out by looking.
This is worth doing before you order anything, because the fix is cheap at the design stage: recode the internal codon synonymously so it is no longer a start codon, or break the purine run upstream of it. Afterwards, the symptom is a doublet on a gel that you will spend a week attributing to proteolysis.
What the prediction does not cover
Being specific about this is more useful than a general disclaimer, because each gap maps to a different thing going wrong.
It models initiation only. Transcription, elongation, mRNA stability, protein folding and toxicity are all outside it — a construct with a perfect predicted initiation rate can still give you nothing because the promoter is off, the mRNA is degraded, or the protein kills the cell.
It is parameterised on E. coli. The anti-SD sequence is the only host parameter, so supplying a different organism's 16S 3' end adjusts the hybridisation term and nothing else; the fitted coefficients still come from E. coli measurements.
It does not know about your cloning. A designed 5' UTR can contain a restriction site you are trying to keep out, a cryptic promoter, or an out-of-frame upstream AUG. Check the sequence you are about to order against your enzyme set and your assembly junctions.
And the error bar it usually gets quoted with is not the one you want. The familiar figures — 53% of measurements within 2-fold and 91% within 10-fold — are calibration residuals over the 132 sequences of Salis et al. 2009 that OSTIR's own coefficients were fitted to. They describe the fit, not performance on a sequence the model has never seen; for that, the published number is a rank correlation of Spearman ρ = 0.39 on datasets it was not fitted to (Gilliot & Gorochowski, Nucleic Acids Res 2024). So read the output as an ordering rather than a magnitude: prefer the higher-scoring design, do not promise yourself a particular fold-improvement, and when two candidates score close together pick on other grounds — whichever one avoids a restriction site, say.
The tooling, and what it costs to run
There are three routes to these numbers and they are not interchangeable.
The Salis lab's RBS Calculator is the original and the most developed line of the model. As of August 2026 its web interface requires an account: the software page presents a login form with "Don't have an account? CREATE A NEW ACCOUNT" and nothing else until you sign in. The calculators are also documented and hosted under the De Novo DNA brand.
OSTIR is the open-source continuation of the last open-source RBS Calculator release, from the Barrick lab at UT Austin, published in JOSS in 2021 (doi:10.21105/joss.03362) and GPL-3.0 licensed. Its coefficients were re-fitted against ViennaRNA's energy parameters, which is why its numbers are not interchangeable with RBS Calculator v2 output — do not compare across the two. Installing it means conda or pip plus a working ViennaRNA Python module, which is the step that stops most people.
SeqBench's RBS Designer runs OSTIR 1.1.2 for you — on its own server rather than in your browser, so there is nothing to install and no account to create; you paste a sequence and read the result. Prediction mode scores every start codon in a pasted mRNA and returns the full five-term breakdown; design mode takes a coding sequence, builds a spread of SD cores and spacings, scores every one in that CDS's own context, and ranks them — optionally against a target rate rather than by maximum strength, and optionally with your existing 5' UTR scored as a baseline so each candidate carries a fold-change. It is the same tool that produced every number in this guide, and the same calculation is available over the REST API and MCP.
Two limits worth knowing before you rely on it. It runs ViennaRNA on a shared service, so it is rate limited and can return a 429 or 503 under load, and the generated spacers are poly-A by construction — an unstructured filler chosen so that spacing is varied without confounding it with new hairpins, which means you should read the returned UTR before cloning it rather than assuming it is compatible with your assembly.
A working recipe
- Score what you have first. Paste the 5' UTR plus the first ~90 nt of the CDS and read the rate at your intended start codon. Without a baseline, every later number is unanchored.
- Read the whole prediction list, not just the strongest. An internal start codon scoring within a few-fold of your real one is a design problem you can still fix cheaply.
- Check which term is limiting. A weak hybridisation term is an SD problem and easy to fix. A large unfolding cost is a structure problem, and the fix is usually in the first few codons of the CDS, not in the UTR.
- Run design mode with your existing UTR as the baseline, so candidates come back as fold-changes rather than bare numbers.
- If you want a specific level rather than the maximum — balancing a two-enzyme pathway, say — supply a target rate. Ranking then favours closeness to the target, and being three-fold over is penalised the same as three-fold under.
- Take the returned UTR and check it as a sequence: restriction sites, upstream out-of-frame starts, and whether it fits your assembly junctions.
- Build two or three candidates spanning the range, not one. The model's own error bar is 2-fold for about half of sequences, which is wide enough that the ranking can be wrong between neighbours.
Frequently asked questions
How do I design a ribosome binding site for a specific gene?
Score candidates against that gene's own coding sequence rather than picking a part from a strength table. Take the CDS starting at its start codon, generate a spread of Shine-Dalgarno cores and SD-to-start spacings, and rank them by predicted initiation rate in that CDS's context — the ranking changes between genes. Include your existing 5' UTR as a baseline so each candidate comes back as a fold-change, and build two or three spanning the range rather than only the top hit.
Is there a free RBS Calculator that doesn't need an account?
Yes. The Salis lab's RBS Calculator web interface requires you to create an account — the software page shows a login form and nothing else. OSTIR, the open-source continuation of the last open-source RBS Calculator release (Barrick lab, GPL-3.0, JOSS 2021), is free but is a command-line Python package that needs ViennaRNA installed. SeqBench's RBS Designer runs OSTIR for you with no install and no account — the calculation happens on SeqBench's own server, not in your browser, so all you do is paste a sequence. Note that OSTIR's coefficients were re-fitted to ViennaRNA's energy model, so its numbers are not interchangeable with RBS Calculator v2 output.
Why does the same RBS give different expression for different genes?
Because the predicted rate depends on the mRNA structure around the initiation site, and the coding sequence's own 5' end is part of that structure. In one measured pair, the identical 38 nt 5' UTR gave 29,915 in front of a GFP CDS and 20,052 in front of an mCherry CDS, with an identical 16S rRNA hybridisation term of −9.08 kcal/mol and unfolding terms of −1.9 and −2.9 kcal/mol. Behind a longer leader the same two constructs sat nine-fold apart. This was reported in the original 2009 method paper and is the main reason a parts-registry strength number does not transfer.
What is the optimal spacing between the Shine-Dalgarno sequence and the start codon?
The model's optimum is an aligned spacing of 5 nt, and the penalty either side is gentler than usually assumed. Sweeping one SD core across spacings in front of the same CDS, the predicted rate fell from 213,098 at 5 nt to 186,010 at 6 nt, 154,233 at 7 nt and 121,481 at 8 nt — about 13% for the first nucleotide off, 43% by three. Spacing is worth getting right, but it is not where a hundred-fold expression problem is hiding.
What do the expression numbers mean — what are the units?
There are none. The value is an exponential of the total free energy: exp(7.279194329 − ΔG(total)/2.4998) in OSTIR, with both constants fitted against the 2009 measurements. Ratios between predictions from the same model are meaningful; the absolute number is not a protein concentration. Because it is exponential, 1 kcal/mol is a factor of 1.49 and a ten-fold change costs 5.76 kcal/mol.
How accurate is a translation initiation rate prediction?
Two different numbers get quoted and the difference is most of the answer. The familiar 53% within 2-fold and 91% within 10-fold are calibration residuals over the 132 sequences of Salis et al. 2009 that OSTIR's coefficients were fitted to — not held-out validation. On data it was not fitted to, OSTIR's rank correlation with measured expression is Spearman ρ = 0.39 (Gilliot & Gorochowski, Nucleic Acids Res 2024;52(13):e58). Practically: use it to order candidates within one construct context, treat two that score close together as indistinguishable, and do not read the absolute value as an expression level. It also models initiation only — transcription, mRNA stability, elongation, folding and toxicity are all outside it, so a good predicted rate is a necessary and not a sufficient condition for protein.
Can I use this for organisms other than E. coli?
Partly. The anti-Shine-Dalgarno sequence — the nine bases at the 3' end of the 16S rRNA, ACCTCCTTA in E. coli — is a parameter you can change to model another host, and doing so adjusts the hybridisation term. Everything else, including the fitted coefficients, still comes from E. coli measurements, so treat cross-species output as a ranking aid rather than a prediction.
My construct makes two protein bands. Could the RBS be the cause?
It can be, if the second band is shorter than the first. Score every start codon in your construct rather than only the intended one: an internal in-frame AUG with a purine-rich sequence upstream of it can be a genuine competitor. In one mCherry construct the annotated start scored 20,052 and the gene's own codon-10 AUG scored 6,821, with the strongest hybridisation term in the construct. The fix at design time is a synonymous recode of that codon or of the purine run before it.
What is BBa_B0034's actual strength?
It has none in the abstract. The Registry describes it as "RBS (Elowitz 1999) -- defines RBS efficiency" — it is the reference point the scale was built on, not a measured constant. It is a 12 bp part, AAAGAGGAGAAA, used in 13,384 Registry parts. Scored in context it behaved very differently across two constructs measured here: a re-designed UTR beat it 7.1-fold in front of one CDS and 13.0-fold in front of another.
Related references
Standard genetic code table for translating DNA or RNA codons.
One-letter and three-letter amino acid codes with key properties.
Common restriction enzymes: recognition sites, cut positions, NEB buffer activity, star activity and an interactive double-digest buffer finder.
Related tools
Predict the translation initiation rate at every start codon, and design a 5' UTR to hit a target expression level, with OSTIR and ViennaRNA.
Optimise a protein or CDS for expression in E. coli, human, yeast, CHO, Pichia and more.
Fold an RNA to its minimum-free-energy secondary structure — dot-bracket, MFE, base-pair list and an exportable arc diagram, without installing ViennaRNA.
Find open reading frames in all six frames and translate them.
Scan a coding sequence for premature stops, cryptic RBS/polyA signals, unwanted restriction sites, GC extremes and repeats.
Find recognition and cut sites for common restriction enzymes.