Throwaway Functional Prototypes are a Waste of Time

Throwaway Functional Prototypes are a Waste of Time
Photo by Marsumilae / Unsplash

Picture this, your company wants to wow a new customer by presenting them with a prototype (or MVP?) of their next product. The business goal isn’t necessarily to ship – the app will likely not see real users, yet. Instead, the company wants to establish that it can deliver on quickly, on budget, and with the right level of quality. You want to build trust with the customer.

Now, if the company actually has the right kind of process in place, that may be possible. But, more often than not, nailing all 3 is pretty hard. (The good ole "you can only have two.") So, the leadership starts a "get shit done" death march and pushes tough goals on the team.

The developers will surely raise concerns over the shortcuts they are making. "This isn’t how robust software should be built!" they cry. And their concerns are met with the assurance that this is just a prototype. "It is just a throw away! Once the company secures the customer and gets more money, we can get rid of it and start from scratch."

The developers really want to believe those words, but they are always lies. Most of you know this by now.

There is No Time for a Restart

If the customer likes the product so far and gives your company more money, do you think they care about developers restarting or refactoring? The expectation has been set: you are a team that delivers fast and on budget. From here on, you will be expected to keep that promise. You may get a bit of room at the start (if you’re lucky), but that’s all you can home for.

This is why I really care about my prototyping stack. If I’m going to invest into a functional prototype, then it needs to be ready to grow into a full product. We don’t get a second chance to do it again. The underlying technology should make it easy to deal with the fact that my prototype will definitely be a technical mess.

Here’s what I think you should look for in your stack:

  • Rapid Speed of Development: The chosen stack should facilitate rapid iteration and development cycles. This allows for quick experimentation, learning, and refining of the prototype based on user feedback.
  • Ability to Transition to a Real Product: The prototyping stack should have the potential to evolve into a scalable, production-ready solution seamlessly. This means supporting essential functionalities, data model evolution, and integrations necessary for a fully functioning product.

Choosing Your Tech

The top two contenders in the JavaScript world are Firebase and Supabase. They cover the rapid part and give you a lot of things that you’ll need as you transition to a real product. Amazon offers AWS Amplify, which sports the same core features, but lags in terms of developer experience. There’s a lot of boilerplates and starter templates aimed at these products that can give you a well-structured setup from day 1.

I’ve used all three to build a functional prototype and transition it to a growing product with real users. If there’s only one advice you take away from this is to pick one and learn it really well – especially if your business context often requires you to go from MVP to growth.

But don’t just focus on the rapid part, think and care deeply about how you can be productive with this stack in the future.

Consider these scenarios and plan ahead:

  • How will you quickly add new required fields? How will you run code that backfills those fields for existing entries? If the data needs to come from some place (an API, a database), how will your backfill mechanism handle it?
  • Can you build for a multi-tenant system from the start? If you can’t, how will you transition to it?
  • Can you emit custom events anywhere in your system? Can you write code that can ingest them from a single event bus and respond to them?
  • How difficult will it be to add an activity stream?
  • Do you know how you would build audit logs in the future?
  • Can you quickly introduce different plans/tiers? What about usage-based tiers?
  • If you are charging by time/resource usage, what will it take to collect and store that information for accurate billing?

Prioritize the recurring activities. This is where your stack should provide the most value.

As you are prototyping none of these questions matter. Data migration and schema management is not a thing – you just delete and start from scratch. But as soon as you sign your first real user this has to change.

After CRUD and Events, Solve Background Jobs

Your product will eventually grow to need some sort of background jobs. There’s a lot of solutions for small activities (such AWS Lambda or Google’s Cloud Function), but what about compute-intensive jobs?

Does your stack and ecosystem already have the right options that integrate well together, or will you need to look for another provider? How long will take to set that up? Will you be able to build other "glue logic" around things happening on this other platform?

Also, think about how tough it could be to handle scheduling for these jobs – especially if you’re letting users configure it.

For me, going all in on one cloud provider really makes life easier. For example, with AWS we can get everything in one package:

  • Prototype quickly via AWS Amplify to spin up our real-time CRUD app.
  • With S3 we get the cheapest blob storage on the market. (And lifecycle rules make it easy to save money further via scheduled deletes or moving things to Glacier.)
  • We can emit events via CloudWatch and use EventBridge rules to trigger the right Lambdas to perform the actions we need. Is the process a bit more complex than a single Lambda? Then construct a simple StepFunction to orchestrate a flow.
  • Need a queue? SQS is awesome and can be configured with only 5 lines of CDK.
  • With DynamoDB we can easily move data around, migrate it, add highly performant cashing (DAX), and setup awesome searching capabilities via AWS OpenSearch (quite expensive though!).
  • For background jobs we have a lot of options via Fargate and Glue.

You can get a very similar experience with Google Cloud as well: Firebase, GC Storage, Pub/Sub, GC Functions, GC Tasks, Firestore, GC Run, and Algolia/Elasticsearch integrations.

It doesn’t matter which one of these is "the best". What matters is that you specialize in particular stack and find ways to get so good at developing software that the line blurs between what is a prototype and what is "real" software from day 1.

Don’t waste time on the idea of throwaway work. Be so good that they can’t ignore you!

Filip Danic

Filip Danic

Software Development Manager at Amazon and recovering JavaScript enthusiast. Sharing my experience and insights with the broader tech community via this blog!
The Netherlands